@avalabs/svm-module 3.0.4 → 3.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/module.ts","../../../packages-internal/utils/src/services/token-service/token-service.ts","../../../packages-internal/utils/src/utils/retry.ts","../../../packages-internal/utils/src/utils/coingecko-retry.ts","../../../packages-internal/utils/src/utils/charsum.ts","../../../packages-internal/utils/src/utils/array-hash.ts","../../../packages-internal/utils/src/services/token-service/coingecko-proxy-client.ts","../../../packages-internal/utils/src/utils/fetch-and-verify.ts","../../../packages-internal/utils/src/services/token-service/watchlist-proxy-client.ts","../../../packages-internal/utils/src/services/pricing-service/exchange-rates.ts","../../../packages-internal/utils/src/utils/detail-item.ts","../../../packages-internal/utils/src/utils/get-core-headers.ts","../../../packages-internal/utils/src/consts.ts","../../../packages-internal/utils/src/utils/get-glacier-api-key.ts","../../../packages-internal/utils/src/utils/glacier-fetch-http-request.ts","../manifest.json","../src/env.ts","../src/handlers/derive-address/derive-address.ts","../../../packages-internal/utils/src/utils/address-derivation.ts","../src/handlers/build-derivation-path/build-derivation-path.ts","../src/handlers/get-network-fee/get-network-fee.ts","../src/utils/get-provider.ts","../src/constants.ts","../src/handlers/get-tokens/get-tokens.ts","../src/handlers/get-tokens/spl-token-schema.ts","../src/handlers/get-balances/get-balances.ts","../src/utils/moralis-service/moralis-schemas.ts","../src/utils/moralis-service/moralis-service.ts","../src/utils/get-network-name.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-transaction-history/extract-transfer.ts","../src/handlers/get-transaction-history/get-wrapped-transactions.ts","../../../packages-internal/utils/src/utils/is-promise-fulfilled.ts","../src/utils/has-property-defined.ts","../src/handlers/get-transaction-history/get-explorer-link.ts","../src/handlers/sign-and-send-transaction/sign-and-send-transaction.ts","../src/utils/explain/explain-transaction.ts","../src/utils/transaction-alerts.ts","../src/utils/explain/parse-transaction.ts","../src/utils/functional.ts","../src/utils/explain/instruction-parsers/sol-transfer.ts","../src/utils/explain/instruction-parsers/spl-transfer.ts","../src/utils/explain/blockaid/process-balance-change.ts","../src/utils/explain/blockaid/scan-solana-transaction.ts","../src/utils/wait-for-transaction-confirmation.ts","../src/utils/get-explorer-address-by-network.ts","../src/handlers/sign-and-send-transaction/schema.ts","../src/handlers/sign-transaction/sign-transaction.ts","../src/handlers/sign-transaction/schema.ts","../src/handlers/sign-message/sign-message.ts","../src/utils/is-transaction-bytes.ts","../src/handlers/sign-message/schema.ts"],"names":["parseManifest","RpcMethod","rpcErrors","VsCurrencyType","getBasicCoingeckoHttp","simplePrice","simpleTokenPrice","retry","operation","isSuccess","maxRetries","backoffPolicy","RetryBackoffPolicy","backoffPeriodMillis","retries","lastError","delay","result","err","errorMessage","retryIndex","secondsToDelay","_","msToDelay","linearCount","linearStepMs","n","base","incSum","ms","r","coingeckoRetry","response","charsum","s","i","sum","arrayHash","array","cs","RawSimplePriceResponseSchema","fetchAndVerify","fetchOptions","schema","responseJson","CoingeckoProxyClient","proxyApiUrl","params","queryParams","id","rawQueryParams","z","WatchlistTokenResponseSchema","WatchlistProxyClient","coingeckoBasicClient","_storage","_proxyApiUrl","TokenService","storage","__privateAdd","__publicField","data","currencies","formattedData","tokenData","currency","__privateSet","tokenDetails","tokenInfo","__privateGet","token","coinIds","cacheId","useCoingeckoProxy","tokenAddresses","assetPlatformId","rawData","marketCap","vol24","change24","lastUpdated","shouldThrow","number","object","record","string","ExchangeRateSchema","DetailItemType","textItem","label","value","alignment","addressItem","addressListItem","dataItem","AppName","GLACIER_API_KEY","getGlacierApiKey","GLOBAL_QUERY_PARAMS","manifest_default","Environment","prodEnv","devEnv","getEnv","environment","NetworkVMType","base58","hex","hasDerivationDetails","buildDerivationPath","accountIndex","deriveAddress","approvalController","secretId","derivationPath","publicKeyHex","getSolanaProvider","SOLANA_MAINNET_CAIP2_ID","SOLANA_DEVNET_CAIP2_ID","SOLANA_TESTNET_CAIP2_ID","RPC_URL_PROXY_API_ENDPOINT","RPC_URL_DEVNET","BLOCKAID_API_KEY","getProvider","isTestnet","LamportsMultiplier","DEFAULT_PRIORITY_FEE","ensureEnoughData","fees","a","b","getNetworkFee","network","feesRaw","block","sortedFees","minFeeInRecentBlocks","maxFeeInRecentBlocks","midIndex","medianFee","presetHigh","presetMedium","presetLow","TokenType","SPL_TOKEN_SCHEMA","SPL_TOKENS_SCHEMA","getTokens","caip2Id","error","TokenUnit","PORTFOLIO_SCHEMA","_baseUrl","_buildUrl","buildUrl_fn","MoralisService","address","url","__privateMethod","portfolio","message","path","getNetworkName","getBalances","addresses","tokenService","moralisService","coingeckoAssetId","coingeckoPlatformId","lowercaseCurrency","solanaNetwork","portfolioResults","mints","mint","tokenPrices","nativeMarketData","portfolioAcc","nativeBalanceUnit","nativeBalanceInCurrency","solanaBalance","tokenBalances","tokensAcc","amountRaw","symbol","decimals","name","logo","balanceUnit","marketData","getMarketData","balanceInCurrency","coinIdOrAddress","prices","TransactionType","simplifyTokenBalance","balance","extractTokenTranfers","meta","ourAddress","preBalances","acc","owner","amount","transfers","key","preAmount","netChange","isReceive","isSend","sender","k","possibleSender","mintFromPreBalance","preBalance","postBalance","postMint","t","transfer","recipient","postBalanceOwner","postBalanceMint","p","nativeTransfer","extractNativeTransfer","paidFee","postBalances","splTransfers","ourAccountIndex","addr","nativeBalancePre","rawBalanceChange","solSpent","unit","largestSOLRecipient","max","diff","balanceDiffs","isSwapContext","nativeTransferAmount","isIncoming","counterpartyIndex","isSOLtoSPLSwap","receivedSPL","sentSPL","largestGainer","largestBeneficiary","index","change","counterpartyAddress","fromAddress","toAddress","solAddress","isFulfilled","hasPropertyDefined","thing","getWrappedTransactions","provider","mainSignatures","sig","allSignatures","networkName","portfolioResult","tokenATAs","nftATAs","nft","ataSignaturePromises","ataAddress","ataSignatures","tx","getExplorerLink","txHash","baseUrl","explorerLink","getTransactionHistory","isOurAddressInTransaction","isSigner","txType","inferTxType","ourTransfers","hasSending","hasReceiving","AlertType","getAlertForError","transactionAlerts","deserializeTransactionMessage","isBalanceChangeEmpty","input","isNotNullish","identifySystemInstruction","parseTransferSolInstruction","SYSTEM_PROGRAM_ADDRESS","SystemInstruction","isInstructionForProgram","isInstructionWithAccounts","isInstructionWithData","tryToParseSolTransfer","instruction","balanceChange","account","networkToken","accounts","balanceChangeKey","parseTransferInstruction","identifyTokenInstruction","TokenInstruction","parseTransferCheckedInstruction","getTokenMintFromAccountInfo","tokenAccountDetails","info","tryToParseSPLTransfer","tokens","tokenInstruction","parser","tokenMint","parseTransaction","serializedTx","transaction","details","results","processBalanceChange","simulationResult","transferedAssets","inTokenDiffDict","outTokenDiffDict","otherAffectedAddresses","asset","assetIn","assetOut","convertDiffAssetToToken","identifier","convertNativeAssetToToken","convertTokenAssetToToken","base64","scanSolanaTransaction","dAppUrl","blockaid","explainTransaction","simulationParams","scanResponse","simulation","validation","genericDetails","isSimulationSuccessful","alert","processedBalanceChange","accountAssetsDiff","outgoingAssets","incomingAssets","parsedBalanceChange","parsedDetails","signature","fallbackExplorerUrl","getExplorerAddressByNetwork","hash","hashType","POLLING_INTERVAL","MAX_RETRIES","waitForTransactionConfirmation","request","commitment","lastStatus","resolve","confirmationStatus","transactionSchema","paramsSchema","parseRequestParams","signAndSendTransaction","success","sendOptions","displayData","signingData","getTxHash","signTransaction","getCompiledTransactionMessageDecoder","isTransactionBytes","base64Payload","bytes","signMessageSchema","serializedMessage","signMessage","utf8Decoder","Blockaid","_approvalController","_appInfo","_blockaid","SvmModule","appInfo","runtime"],"mappings":"uEAAA,OACE,iBAAAA,GACA,aAAAC,OAYK,2BAEP,OAAS,aAAAC,OAAiB,uBChB1B,OACE,kBAAAC,EACA,yBAAAC,GACA,eAAAC,GACA,oBAAAC,OAEK,8BCsBA,IAAMC,GAAQ,MAAU,CAC7B,UAAAC,EACA,UAAAC,EACA,WAAAC,EAAa,GACb,cAAAC,EAAgBC,EAAmB,YAAY,CACjD,IAAkC,CAChC,IAAIC,EAAsB,EACtBC,EAAU,EACVC,EAEJ,KAAOD,EAAUJ,GAAY,CACvBI,EAAU,GACZ,MAAME,GAAMH,CAAmB,EAGjC,GAAI,CACF,IAAMI,EAAS,MAAMT,EAAUM,CAAO,EAEtC,GAAIL,EAAUQ,CAAM,EAClB,OAAOA,CAEX,OAASC,EAAK,CAEZH,EAAYG,CACd,CAEAL,EAAsBF,EAAcG,CAAO,EAC3CA,GACF,CAEA,IAAMK,EAAeJ,EAAY,uBAAuBA,CAAS,GAAK,sBAEtE,MAAM,IAAI,MAAMI,CAAY,CAC9B,EAIaP,EAAN,KAAyB,CAC9B,OAAO,aAA2C,CAChD,OAAQQ,GACC,KAAK,IAAI,EAAGA,CAAU,EAAI,GAErC,CAEA,OAAO,SAASC,EAAqD,CACnE,OAAQC,GACCD,EAAiB,GAE5B,CAEA,OAAO,WAAWE,EAAgD,CAChE,OAAQD,GACCC,CAEX,CASA,OAAO,sBAAsBC,EAAqBC,EAAmD,CACnG,OAAQL,GAA+B,CACrC,GAAIA,EAAaI,EAEf,OAAQJ,EAAa,GAAKK,EAM5B,IAAMC,EAAIN,EAAaI,EAAc,EAC/BG,EAAOH,EAAcC,EACrBG,EAAS,EAAIH,GAAgB,KAAK,IAAI,EAAGC,CAAC,EAAI,GACpD,OAAOC,EAAOC,CAChB,CACF,CACF,EAEA,SAASZ,GAAMa,EAAY,CACzB,OAAO,IAAI,QAASC,GAAM,WAAWA,EAAGD,CAAE,CAAC,CAC7C,CCtGO,IAAME,GACXvB,GAEOD,GAAM,CACX,UAAYa,GAAuBZ,EAAUY,EAAa,CAAC,EAC3D,WAAY,EACZ,cAAeR,EAAmB,SAAS,CAAC,EAC5C,UAAYoB,GACWA,GAAoB,QACrB,aAAe,GAEvC,CAAC,ECpBI,SAASC,GAAQC,EAAmB,CACzC,IAAIC,EACFC,EAAM,EACR,IAAKD,EAAI,EAAGA,EAAID,EAAE,OAAQC,IACxBC,GAAOF,EAAE,WAAWC,CAAC,GAAKA,EAAI,GAEhC,OAAOC,CACT,CCJO,SAASC,GAAUC,EAAyB,CACjD,IAAIH,EACFC,EAAM,EACR,IAAKD,EAAI,EAAGA,EAAIG,EAAM,OAAQH,IAAK,CACjC,IAAMI,EAAKN,GAAQK,EAAMH,CAAC,GAAK,EAAE,EACjCC,EAAMA,EAAM,MAAQG,CACtB,CACA,OAAQ,GAAKH,GAAK,MAAM,EAAG,EAAE,CAC/B,CCXA,OAAS,gCAAAI,OAAoC,2BCA7C,MAAc,MAGd,eAAsBC,EACpBC,EACAC,EACqB,CACrB,IAAMX,EAAW,MAAM,MAAM,GAAGU,CAAY,EAE5C,GAAI,CAACV,EAAS,GACZ,MAAM,IAAI,MAAM,8BAA8BA,EAAS,MAAM,EAAE,EAGjE,IAAMY,EAAe,MAAMZ,EAAS,KAAK,EACzC,OAAOW,EAAO,MAAMC,CAAY,CAClC,CDZO,IAAMC,EAAN,KAA2B,CAChC,YAAoBC,EAAqB,CAArB,iBAAAA,CAAsB,CAE1C,YAAYC,EAOT,CAID,IAAMC,EAAc,IAAI,gBAAgBD,CAAa,EACrD,OAAON,EACL,CACE,GAAG,KAAK,WAAW,iCAAiCO,CAAW,GAC/D,CACE,OAAQ,OACR,QAAS,CACP,eAAgB,kBAClB,CACF,CACF,EACAR,EACF,CACF,CAEA,+BAA+BO,EAO5B,CACD,GAAM,CAAE,GAAAE,EAAI,GAAGC,CAAe,EAAIH,EAK5BC,EAAc,IAAI,gBAAgBE,CAAqB,EAE7D,OAAOT,EACL,CACE,GAAG,KAAK,WAAW,uCAAuCQ,CAAE,IAAID,CAAW,GAC3E,CACE,OAAQ,OACR,QAAS,CACP,eAAgB,kBAClB,CACF,CACF,EACAR,EACF,CACF,CACF,EE3DA,OAAS,KAAAW,MAAS,MAElB,IAAMC,GAA+BD,EAAE,MACrCA,EAAE,OAAO,CAEP,WAAYA,EAAE,OAAO,EACrB,GAAIA,EAAE,OAAO,EACb,OAAQA,EAAE,OAAO,EACjB,KAAMA,EAAE,OAAO,EACf,MAAOA,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EACtC,cAAeA,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAC9C,4BAA6BA,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAC5D,WAAYA,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAC3C,aAAcA,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAC7C,UAAWA,EAAE,OAAOA,EAAE,OAAO,EAAGA,EAAE,OAAO,CAAC,CAC5C,CAAC,CACH,EAEaE,GAAN,KAA2B,CAChC,YAAoBP,EAAqB,CAArB,iBAAAA,CAAsB,CAE1C,eAAeC,EAA8C,CAI3D,IAAMC,EAAc,IAAI,gBAAgBD,CAAa,EACrD,OAAON,EACL,CACE,GAAG,KAAK,WAAW,qBAAqBO,CAAW,GACnD,CACE,OAAQ,MACR,QAAS,CACP,eAAgB,kBAClB,CACF,CACF,EACAI,EACF,CACF,CACF,EP3BA,IAAME,GAAuBlD,GAAsB,EAbnDmD,EAAAC,EAeaC,EAAN,KAAmB,CAIxB,YAAY,CAAE,QAAAC,EAAS,YAAAZ,CAAY,EAA+C,CAHlFa,EAAA,KAAAJ,EAAA,QACAI,EAAA,KAAAH,EAAA,QAkMAI,GAAA,KAAQ,+BAA+B,CACrCC,EACAC,EAAa,CAAC3D,EAAe,GAAG,IACR,CACxB,IAAM4D,EAAqC,CAAC,EAC5C,cAAO,KAAKF,CAAI,EAAE,QAASZ,GAAO,CAChC,IAAMe,EAAYH,EAAKZ,CAAE,EACzBc,EAAcd,CAAE,EAAI,CAAC,EACrBa,EAAW,QAASG,GAA6B,CAC/CF,EAAcd,CAAE,EAAI,CAClB,CAACgB,CAAQ,EAAG,CACV,MAAOD,IAAYC,CAAQ,EAC3B,SAAUD,IAAY,GAAGC,CAAQ,aAAa,EAC9C,MAAOD,IAAY,GAAGC,CAAQ,UAAU,EACxC,UAAWD,IAAY,GAAGC,CAAQ,aAAa,CACjD,CACF,CACF,CAAC,CACH,CAAC,EACMF,CACT,GAnNEG,EAAA,KAAKX,EAAWG,GAChBQ,EAAA,KAAKV,EAAeV,EACtB,CAEA,MAAM,yBAAyB,CAC7B,aAAAqB,EACA,SAAAF,EAAW9D,EAAe,GAC5B,EAaG,CAYD,IAAMiE,GAVJ,MAAM,IAAIf,GAAqBgB,EAAA,KAAKb,EAAY,EAAE,eAAe,CAC/D,OAAQW,EAAa,OACrB,SAAUF,CACZ,CAAC,GACD,OAAQK,GACDH,EAAa,SAChBG,EAAM,aAAe,UAAUH,EAAa,OAAO,YAAY,CAAC,GAChEG,EAAM,UAAUH,EAAa,OAAO,IAAMA,EAAa,OAC5D,EAEsB,CAAC,EAExB,OAAKC,EASE,CACL,gBAAiBA,EAAU,eAAiB,EAC5C,SAAUA,EAAU,6BAA+B,EACnD,UAAWA,EAAU,YAAc,EACnC,MAAOA,EAAU,cAAgB,CACnC,EAbS,CACL,gBAAiB,EACjB,SAAU,EACV,UAAW,EACX,MAAO,CACT,CASJ,CAOA,MAAM,eAAe,CACnB,QAAAG,EAAU,CAAC,EACX,WAAAT,EAAa,CAAC3D,EAAe,GAAG,CAClC,EAAgE,CAC9D,IAAI0D,EAIEW,EAAU,kBAFJD,EAAU,GAAGlC,GAAUkC,CAAO,CAAC,IAAIT,EAAW,SAAS,CAAC,GAAK,GAAGA,EAAW,SAAS,CAAC,EAE5D,GAIrC,GAFAD,EAAOQ,EAAA,KAAKd,IAAU,MAA2BiB,CAAO,EAEpDX,EAAM,OAAOA,EAEjB,GAAI,CACFA,EAAO,MAAM9B,GAAgB0C,GAC3B,KAAK,YAAY,CACf,QAAAF,EACA,WAAAT,EACA,UAAW,GACX,MAAO,GACP,SAAU,GACV,kBAAAW,CACF,CAAC,CACH,CACF,MAAQ,CACNZ,EAAO,MACT,CACA,OAAAQ,EAAA,KAAKd,IAAU,MAAMiB,EAASX,CAAI,EAC3BA,CACT,CASA,MAAM,qBACJa,EACAC,EACAV,EAA2B9D,EAAe,IACA,CAC1C,IAAI0D,EAIEW,EAAU,sCAFJ,GAAGnC,GAAUqC,CAAc,CAAC,IAAIC,CAAe,IAAIV,CAAQ,EAEd,GAGzD,GAFAJ,EAAOQ,EAAA,KAAKd,IAAU,MAA2BiB,CAAO,EAEpDX,EAAM,OAAOA,EAEjB,GAAI,CACFA,EAAO,MAAM9B,GAAgB0C,GAC3B,KAAK,uBAAuB,CAC1B,gBAAAE,EACA,eAAAD,EACA,SAAAT,EACA,kBAAAQ,CACF,CAAC,CACH,CACF,OAASvD,EAAK,CACZ,QAAQ,MAAMA,CAAG,EACjB2C,EAAO,MACT,CACA,OAAAQ,EAAA,KAAKd,IAAU,MAAMiB,EAASX,CAAI,EAC3BA,CACT,CAEA,MAAc,uBAAuB,CACnC,gBAAAc,EACA,eAAAD,EACA,SAAAT,EAAW9D,EAAe,IAC1B,kBAAAsE,EAAoB,EACtB,EAKiC,CAC/B,GAAIA,EAAmB,CACrB,IAAMG,EAAU,MAAM,IAAI/B,EAAqBwB,EAAA,KAAKb,EAAY,EAAE,+BAA+B,CAC/F,GAAImB,EACJ,mBAAoBD,EACpB,cAAe,CAACT,CAAQ,EACxB,mBAAoB,GACpB,iBAAkB,GAClB,oBAAqB,EACvB,CAAC,EACD,OAAO,KAAK,6BAA6BW,EAAS,CAACX,CAAQ,CAAC,CAC9D,CAEA,OAAO3D,GAAiBgD,GAAsB,CAC5C,gBAAAqB,EACA,eAAAD,EACA,WAAY,CAACT,CAAQ,EACrB,UAAW,GACX,MAAO,GACP,SAAU,EACZ,CAAC,CACH,CAEA,MAAc,YAAY,CACxB,QAAAM,EAAU,CAAC,EACX,WAAAT,EAAa,CAAC3D,EAAe,GAAG,EAChC,UAAA0E,EAAY,GACZ,MAAAC,EAAQ,GACR,SAAAC,EAAW,GACX,YAAAC,EAAc,GACd,kBAAAP,EAAoB,GACpB,YAAAQ,EAAc,EAChB,EAAsF,CACpF,GAAIR,EAAmB,CACrB,IAAMG,EAAU,MAAM,IAAI/B,EAAqBwB,EAAA,KAAKb,EAAY,EAAE,YAAY,CAC5E,IAAKe,EACL,cAAeT,EACf,mBAAoBe,EACpB,iBAAkBC,EAClB,oBAAqBC,EACrB,wBAAyBC,CAC3B,CAAC,EACD,OAAO,KAAK,6BAA6BJ,EAASd,CAAU,CAC9D,CACA,OAAOzD,GAAYiD,GAAsB,CACvC,QAAAiB,EACA,WAAAT,EACA,UAAAe,EACA,MAAAC,EACA,SAAAC,EACA,YAAAC,EACA,YAAAC,CACF,CAAC,CACH,CAuBF,EAxNE1B,EAAA,YACAC,EAAA,YQjBF,OAAY,UAAA0B,GAAQ,UAAAC,GAAQ,UAAAC,GAAQ,UAAAC,OAAc,MAQlD,IAAMC,GAAqBH,GAAO,CAChC,KAAME,GAAO,EACb,IAAKD,GAAOF,GAAO,CAAC,CACtB,CAAC,ECXD,OAQE,kBAAAK,OAMK,2BAuBA,IAAMC,GAAW,CACtBC,EACAC,EACAC,EAAuC,gBACzB,CACd,MAAAF,EACA,UAAAE,EACA,KAAMJ,GAAe,KACrB,MAAAG,CACF,GAQO,IAAME,EAAc,CAACH,EAAeC,KAAgC,CACzE,MAAAD,EACA,KAAMF,GAAe,QACrB,MAAAG,CACF,GAEaG,GAAkB,CAACJ,EAAeC,KAAsC,CACnF,MAAAD,EACA,KAAMF,GAAe,aACrB,MAAAG,CACF,GAQO,IAAMI,GAAW,CAACL,EAAeC,KAA6B,CACnE,MAAAD,EACA,KAAMF,GAAe,KACrB,MAAAG,CACF,GC5EA,OAAS,WAAAK,OAA6B,2BCA/B,IAAMC,GAAkB,QAAQ,IAAI,gBCIpC,IAAMC,GAAmB,IACvBD,GCFT,IAAME,GAA0D,CAC9D,QAASD,GAAiB,CAC5B,ECLA,IAAAE,GAAA,CACE,KAAQ,MACR,YAAe,GACf,QAAW,QACX,QAAW,CACT,OAAU,CACR,SAAY,GACZ,SAAY,CACV,IAAO,CACL,SAAY,gBACZ,YAAe,sBACf,SAAY,4BACd,CACF,CACF,EACA,SAAY,CACV,SAAY,GACZ,SAAY,CACV,IAAO,CACL,SAAY,yBACZ,YAAe,sBACf,SAAY,4BACd,CACF,CACF,CACF,EACA,QAAW,CACT,SAAY,CACV,0CACA,0CACA,yCACF,EACA,WAAc,CAAC,QAAQ,CACzB,EACA,SAAY,MACZ,YAAe,CACb,IAAO,CACL,MAAS,GACT,QAAW,CAAC,yBAA0B,gCAAiC,oBAAoB,EAC3F,qBAAwB,CAAC,CAC3B,CACF,EACA,gBAAmB,KACrB,EC3CA,OAAS,eAAAC,OAAmB,2BAMrB,IAAMC,GAAe,CAC1B,YAAa,gCACf,EAEaC,GAAc,CACzB,YAAa,oCACf,EAEaC,GAAUC,GAAkC,CACvD,OAAQA,EAAa,CACnB,KAAKJ,GAAY,WACf,OAAOC,GACT,KAAKD,GAAY,IACf,OAAOE,EACX,CACF,ECpBA,OAAS,iBAAAG,OAAqB,2BAC9B,OAAS,UAAAC,GAAQ,OAAAC,OAAW,cCArB,IAAMC,GAAwB7D,GACnC,uBAAwBA,GACxB,iBAAkBA,GAClB,OAAOA,EAAO,cAAiB,UAC/B,OAAOA,EAAO,oBAAuB,SCNvC,OACE,iBAAA0D,OAGK,2BACP,OAAS,aAAAvG,OAAiB,uBAMnB,IAAM2G,GAAsB,CAAC,CAClC,aAAAC,CACF,IAAuF,CACrF,GAAIA,EAAe,EACjB,MAAM5G,GAAU,cAAc,8CAA8C,EAG9E,MAAO,CACL,CAACuG,GAAc,GAAG,EAAG,cAAcK,CAAY,MACjD,CACF,EFdO,IAAMC,GAAgB,MAC3BhE,GACmC,CACnC,GAAM,CAAE,mBAAAiE,EAAoB,SAAAC,CAAS,EAAIlE,EAGnCmE,EAAiBN,GAAqB7D,CAAM,EAAI8D,GAAoB9D,CAAM,EAAE,IAAM,OAClFoE,EAAe,MAAMH,EAAmB,iBAAiB,CAC7D,MAAO,UACP,SAAAC,EACA,eAAAC,CACF,CAAC,EAED,MAAO,CACL,CAACT,GAAc,GAAG,EAAGC,GAAO,OAAOC,GAAI,OAAOQ,CAAY,CAAC,CAC7D,CACF,EGvBA,MAAuD,2BCAvD,OAAS,qBAAAC,OAA8C,4BCGhD,IAAMC,GAA0B,0CAC1BC,GAAyB,0CACzBC,GAA0B,0CAE1BC,GAA6B,sBAC7BC,GAAiB,gCAGvB,IAAMC,GAAmB,gBDPzB,IAAMC,EAAc,CAAC,CAC1B,UAAAC,EACA,YAAA9E,CACF,IAISsE,GAAkB,CACvB,UAAAQ,EACA,OAAQA,EAAYH,GAAiB3E,EAAc0E,EACrD,CAAC,EDTH,IAAMK,GAAqB,IACdC,EAAuB,CAClC,KAAM,IAAMD,GACZ,OAAQ,GAAKA,GACb,IAAK,EAAIA,EACX,EAIME,GAAoBC,IAEtBA,EAAK,SAAW,EACZ,CAACF,EAAqB,IAAKA,EAAqB,GAAG,EACnDE,EAAK,SAAW,EAChB,CAACA,EAAK,CAAC,EAAIF,EAAqB,GAAG,EACnCE,GAEgB,MAAM,EAAE,KAAK,CAACC,EAAGC,IAAMD,EAAIC,CAAC,EAuBpD,eAAsBC,GAAcC,EAA0BtF,EAA2C,CAIvG,IAAMuF,EAAU,MADA,MAFCV,EAAY,CAAE,UAAW,EAAQS,EAAQ,UAAY,YAAAtF,CAAY,CAAC,EAEpD,4BAA4B,GAC7B,KAAK,EAInC,GAFuBuF,EAAQ,SAAW,GAAKA,EAAQ,MAAOC,GAAUA,EAAM,oBAAsB,EAAE,EAGpG,MAAO,CACL,KAAM,CACJ,aAAc,OAAOR,EAAqB,IAAI,EAC9C,qBAAsB,OAAOA,EAAqB,IAAI,CACxD,EACA,OAAQ,CACN,aAAc,OAAOA,EAAqB,MAAM,EAChD,qBAAsB,OAAOA,EAAqB,MAAM,CAC1D,EACA,IAAK,CACH,aAAc,OAAOA,EAAqB,GAAG,EAC7C,qBAAsB,OAAOA,EAAqB,GAAG,CACvD,EACA,QAAS,OAAOA,EAAqB,GAAG,EACxC,gBAAiB,EACjB,WAAY,EACd,EAGF,IAAMS,EAAaR,GAAiBM,EAAQ,IAAKC,GAAU,OAAOA,EAAM,iBAAiB,CAAC,CAAC,EAErFE,EAAuBD,EAAW,GAAG,CAAC,EACtCE,EAAuBF,EAAW,GAAG,EAAE,EACvCG,EAAW,KAAK,MAAMH,EAAW,OAAS,CAAC,EAC3CI,EACJJ,EAAW,OAAS,IAAM,EACrBA,EAAWG,CAAQ,GACnBH,EAAWG,EAAW,CAAC,EAAKH,EAAWG,CAAQ,GAAM,EAKtDE,EAAa,OAAO,KAAK,KAAKH,EAAuB,IAAI,CAAC,EAC1DI,EAAe,OAAO,KAAK,KAAKF,EAAY,IAAI,CAAC,EACjDG,EAAY,OAAO,KAAK,KAAKN,EAAuB,IAAI,CAAC,EAG/D,MAAO,CACL,KAAM,CACJ,aAAcI,EACd,qBAAsBA,CACxB,EACA,OAAQ,CACN,aAAcC,EACd,qBAAsBA,CACxB,EACA,IAAK,CACH,aAAcC,EACd,qBAAsBA,CACxB,EACA,QAASA,EACT,gBAAiB,EACjB,WAAY,EACd,CACF,CG1GA,OAAS,aAAA5I,OAAiB,uBCF1B,OAAS,aAAA6I,OAAiB,2BAC1B,OAAS,KAAA5F,MAAS,MAEX,IAAM6F,GAAmB7F,EAAE,OAAO,CACvC,QAASA,EAAE,OAAO,EAClB,KAAMA,EAAE,OAAO,EACf,OAAQA,EAAE,OAAO,EACjB,aAAcA,EAAE,QAAQ4F,GAAU,GAAG,EACrC,QAAS5F,EAAE,OAAO,EAAE,WAAW,SAAS,EACxC,SAAUA,EAAE,OAAO,EACnB,QAASA,EAAE,OAAO,EAAE,SAAS,EAC7B,QAASA,EAAE,OAAO,EAAE,SAAS,EAC7B,MAAOA,EAAE,OAAO,EAAE,SAAS,CAC7B,CAAC,EAEY8F,GAAoB9F,EAAE,MAAM6F,EAAgB,EDVzD,eAAsBE,GAAU,CAC9B,QAAAC,EACA,YAAArG,CACF,EAGwB,CACtB,GAAI,CAGF,OAFe,MAAML,EAAe,CAAC,GAAGK,CAAW,0BAA0BqG,CAAO,EAAE,EAAGF,EAAiB,GAE5F,IAAK3E,IAAW,CAAE,GAAGA,EAAO,KAAMA,EAAM,YAAa,EAAE,CACvE,OAAS8E,EAAO,CACd,cAAQ,MAAM,yBAA0BD,EAASC,CAAK,EAChDlJ,GAAU,SAAS,uCAAuCiJ,CAAO,GAAG,CAC5E,CACF,CEpBA,OAIE,aAAAJ,OAGK,2BACP,OAAS,aAAAM,OAAiB,0BCR1B,OAAS,KAAAlG,MAAS,MAEX,IAAMmG,GAAmBnG,EAAE,OAAO,CACvC,cAAeA,EAAE,OAAO,CACtB,SAAUA,EAAE,OAAO,EACnB,OAAQA,EAAE,OAAO,CACnB,CAAC,EACD,KAAMA,EAAE,MACNA,EAAE,OAAO,CACP,uBAAwBA,EAAE,OAAO,EACjC,KAAMA,EAAE,OAAO,EACf,KAAMA,EAAE,OAAO,EACf,OAAQA,EAAE,OAAO,CACnB,CAAC,CACH,EACA,OAAQA,EAAE,MACRA,EAAE,OAAO,CACP,uBAAwBA,EAAE,OAAO,EACjC,KAAMA,EAAE,OAAO,EACf,UAAWA,EAAE,OAAO,EACpB,OAAQA,EAAE,OAAO,EACjB,SAAUA,EAAE,OAAO,EACnB,KAAMA,EAAE,OAAO,EACf,OAAQA,EAAE,OAAO,EACjB,KAAMA,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CACvC,CAAC,CACH,CACF,CAAC,EC3BD,IAAAoG,GAAAC,GAAAC,GAMaC,EAAN,KAAqB,CAG1B,YAAY,CAAE,YAAA5G,CAAY,EAA4B,CA+BtDa,EAAA,KAAA6F,IAjCA7F,EAAA,KAAA4F,GAAA,QAGErF,EAAA,KAAKqF,GAAW,GAAGzG,CAAW,iBAChC,CAEA,MAAM,aAAa,CACjB,QAAA6G,EACA,QAAAvB,CACF,EAGoG,CAClG,GAAI,CACF,IAAMwB,EAAMC,GAAA,KAAKL,GAAAC,IAAL,UAAe,YAAYrB,CAAO,IAAIuB,CAAO,cACnDG,EAAY,MAAMrH,EAAe,CAACmH,CAAG,EAAGN,EAAgB,EAE9D,MAAO,CACL,QAAAK,EACA,UAAAG,CACF,CACF,OAASV,EAAO,CACd,QAAQ,MAAM,yBAA0BA,CAAK,EAE7C,IAAMW,EAAUX,aAAiB,MAAQA,EAAM,QAAU,gBAEzD,MAAO,CACL,QAAAO,EACA,MAAO,0BAA0BI,CAAO,EAC1C,CACF,CACF,CAKF,EApCER,GAAA,YAiCAC,GAAA,YAAAC,GAAS,SAACO,EAAc,CACtB,MAAO,GAAG3F,EAAA,KAAKkF,GAAQ,GAAGS,CAAI,EAChC,ECtCK,IAAMC,EAAkB7B,GAAqB,CAClD,OAAQA,EAAQ,OAAQ,CACtB,KAAKf,GACH,MAAO,UAET,KAAKC,GACH,MAAO,SAET,KAAKC,GACH,MAAO,UAET,QACE,MAAM,IAAI,MAAM,2BAA6Ba,EAAQ,MAAM,CAC/D,CACF,EHIO,IAAM8B,GAAc,MAAO,CAChC,UAAAC,EACA,YAAArH,EACA,SAAAmB,EACA,QAAAmE,EACA,aAAAgC,CACF,IAG0C,CACxC,IAAMC,EAAiB,IAAIX,EAAe,CAAE,YAAA5G,CAAY,CAAC,EACnDwH,EAAmBlC,EAAQ,kBAAkB,UAAU,eAAiB,GACxEmC,EAAsBnC,EAAQ,kBAAkB,UAAU,iBAAmB,GAC7EoC,EAAoBvG,EAAS,YAAY,EACzCwG,EAAgBR,EAAe7B,CAAO,EAEtCsC,EAAmB,MAAM,QAAQ,IACrCP,EAAU,IAAKR,GAAYU,EAAe,aAAa,CAAE,QAAAV,EAAS,QAASc,CAAc,CAAC,CAAC,CAC7F,EAEME,EAAQ,IAAI,IAChBD,EAAiB,QAASzJ,GACpB,cAAeA,EACVA,EAAO,UAAU,OAAO,IAAI,CAAC,CAAE,KAAA2J,CAAK,IAAMA,CAAI,EAGhD,CAAC,CACT,CACH,EAEMC,EAAc,MAAON,EACvBH,EAAa,qBAAqB,MAAM,KAAKO,CAAK,EAAGJ,EAAqBC,CAAmC,EAC7G,QAAQ,QAAQ,MAAS,GAEvBM,EAAmB,MAAMV,EAAa,yBAAyB,CACnE,aAAc,CACZ,OAAQhC,EAAQ,aAAa,OAC7B,SAAU,GACV,QAASA,EAAQ,QAAU,EAC7B,EACA,SAAUoC,CACZ,CAAC,EAED,OAAOE,EAAiB,OAAO,CAACK,EAAc9J,IAAW,CACvD,GAAI,UAAWA,EACb,MAAO,CACL,GAAG8J,EACH,CAAC9J,EAAO,OAAO,EAAG,CAChB,MAAOA,EAAO,KAChB,CACF,EAGF,IAAM+J,EAAoB,IAAI3B,GAAUpI,EAAO,UAAU,cAAc,SAAU,EAAc,KAAK,EAE9FgK,EACJH,EAAiB,kBAAoB,OACjCE,EAAkB,IAAIF,EAAiB,eAAe,EACtD,OAEAI,EAAqC,CACzC,KAAMnC,GAAU,OAChB,KAAMX,EAAQ,aAAa,KAC3B,OAAQA,EAAQ,aAAa,OAC7B,SAAUA,EAAQ,aAAa,SAC/B,QAAS4C,EAAkB,UAAU,EACrC,oBAAqBA,EAAkB,SAAS,EAChD,kBAAmBC,GAAyB,UAAU,CAAE,QAAS,EAAG,SAAU,EAAK,CAAC,EACpF,4BAA6BA,GAAyB,UAAU,CAAE,QAAS,CAAE,CAAC,EAC9E,QAAS7C,EAAQ,aAAa,SAAW,GACzC,YAAakC,EACb,GAAGQ,CACL,EAEMK,EAAgBlK,EAAO,UAAU,OAAO,OAC5C,CAACmK,EAAW,CAAE,UAAAC,EAAW,OAAAC,EAAQ,SAAAC,EAAU,KAAAX,EAAM,KAAAY,EAAM,KAAAC,CAAK,IAAM,CAChE,IAAMC,EAAc,IAAIrC,GAAUgC,EAAWE,EAAUD,CAAM,EACvDK,EAAaC,GAAchB,EAAMJ,EAAmBK,CAAW,EAC/DgB,GACJF,EAAW,kBAAoB,OAAYD,EAAY,IAAIC,EAAW,eAAe,EAAI,OAErFrH,GAA6B,CACjC,KAAMyE,GAAU,IAChB,QAAS6B,EACT,KAAAY,EACA,OAAAF,EACA,SAAAC,EACA,QAASG,EAAY,UAAU,EAC/B,oBAAqBA,EAAY,SAAS,EAC1C,kBAAmBG,IAAmB,UAAU,CAAE,QAAS,EAAG,SAAU,EAAK,CAAC,EAC9E,4BAA6BA,IAAmB,UAAU,CAAE,QAAS,CAAE,CAAC,EACxE,QAASJ,GAAQ,OACjB,WAAY,KACZ,GAAGE,CACL,EAEA,MAAO,CACL,GAAGP,EACH,CAACR,CAAI,EAAGtG,EACV,CACF,EACA,CAAC,CACH,EAEA,MAAO,CACL,GAAGyG,EACH,CAAC9J,EAAO,OAAO,EAAG,CAChB,CAACmH,EAAQ,aAAa,MAAM,EAAG8C,EAC/B,GAAGC,CACL,CACF,CACF,EAAG,CAAC,CAA8B,CACpC,EAEMS,GAAgB,CAACE,EAAyB7H,EAAkB8H,KAAkC,CAClG,gBAAiBA,IAASD,GAAmB,EAAE,IAAI7H,CAAQ,GAAG,OAAS,OACvE,UAAW8H,IAASD,GAAmB,EAAE,IAAI7H,CAAQ,GAAG,WAAa,OACrE,MAAO8H,IAASD,GAAmB,EAAE,IAAI7H,CAAQ,GAAG,OAAS,OAC7D,SAAU8H,IAASD,GAAmB,EAAE,IAAI7H,CAAQ,GAAG,UAAY,MACrE,GI7IA,OAAS,mBAAA+H,MAAoF,2BAC7F,OAAS,aAAA9L,OAAiB,uBCD1B,OAAS,aAAAmJ,OAAiB,0BAC1B,OAAS,aAAAN,OAA4D,2BAG9D,IAAMkD,GAAwBC,IAA+C,CAClF,KAAMA,EAAQ,KACd,MAAOA,EAAQ,MACf,OAAQ,OAAOA,EAAQ,cAAc,MAAM,EAC3C,SAAUA,EAAQ,cAAc,QAClC,GAEaC,GAAiD,CAAChC,EAAWrD,EAAcsF,EAAMhE,IAAuB,CAEnH,IAAMiE,EACJvF,IAAiB,GACbqD,EAAUrD,CAAY,EACtBsF,EAAK,iBAAiB,KAAMF,GAAY,CAAC/B,EAAU,SAAS+B,EAAQ,KAAK,CAAC,GAAG,OAC7EE,EAAK,kBAAkB,KAAMF,GAAY,CAAC/B,EAAU,SAAS+B,EAAQ,KAAK,CAAC,GAAG,MAG9EI,EAAsCF,EAAK,iBAAiB,OAChE,CAACG,EAAK,CAAE,MAAAC,EAAO,KAAA5B,EAAM,OAAA6B,CAAO,KAAO,CACjC,GAAGF,EACH,CAAC,GAAGC,CAAK,IAAI5B,CAAI,EAAE,EAAG6B,CACxB,GACA,CAAC,CACH,EAGMC,EAAYN,EAAK,kBAAkB,OAAO,CAACG,EAAK,CAAE,MAAAC,EAAO,KAAA5B,EAAM,OAAA6B,EAAQ,SAAAlB,CAAS,IAAM,CAC1F,IAAMoB,EAAM,GAAGH,CAAK,IAAI5B,CAAI,GACtBgC,EAAYN,EAAYK,CAAG,GAAK,GAChCE,EAAYJ,EAASG,EAG3B,GAAIC,IAAc,GAChB,OAAON,EAIT,IAAMO,EAAYD,EAAY,IAAML,IAAUH,EACxCU,EAASF,EAAY,IAAML,IAAUH,EAE3C,GAAIS,EAAW,CAIb,IAAME,EAAS,OAAO,KAAKV,CAAW,EAAE,KAAMW,GAAM,CAClD,GAAM,CAACC,EAAgBC,CAAkB,EAAIF,EAAE,MAAM,GAAG,EAMxD,GAHIE,IAAuBvC,GAGvBsC,IAAmBb,EAAY,MAAO,GAG1C,IAAMe,EAAad,EAAYW,CAAC,EAC1BI,EAAcjB,EAAK,kBAAkB,KACzC,CAAC,CAAE,MAAAI,EAAO,KAAMc,CAAS,IAAMd,IAAUU,GAAkBI,IAAa1C,CAC1E,EAKA,MAFiB,CAACyC,GAAeA,EAAY,OAASD,CAGxD,CAAC,EAED,GAAI,CAACJ,EACH,OAAOT,EAGT,IAAMjI,EACJ8D,EAAQ,QAAQ,OAAQmF,GAAqB,iBAAkBA,CAAC,EAAE,KAAMA,GAAMA,EAAE,UAAY3C,CAAI,GAC/F,CACC,aAAc7B,GAAU,IACxB,SAAAwC,EACA,QAASX,EACT,OAAQ,UACR,KAAM,SACR,EAEI4C,EAAoB,CACxB,GAAGlJ,EACH,KAAMA,EAAM,aACZ,KAAM,CACJ,GAAGA,EACH,QAAS0I,EAAO,MAAM,GAAG,EAAE,CAAC,CAC9B,EACA,GAAI,CACF,GAAG1I,EACH,QAASkI,CACX,EACA,OAAQ,IAAInD,GAAUwD,EAAWtB,EAAU,EAAE,EAAE,UAAU,CAC3D,EAEA,MAAO,CAAC,GAAGgB,EAAKiB,CAAQ,CAC1B,SAAWT,EAAQ,CAGjB,IAAMU,EAAYrB,EAAK,kBAAkB,KACvC,CAAC,CAAE,MAAOsB,EAAkB,KAAMC,CAAgB,IAChDA,IAAoB/C,GACpB8C,IAAqBrB,IACpBC,EAAY,GAAGoB,CAAgB,IAAI9C,CAAI,EAAE,GAAK,KAC5CwB,EAAK,kBAAkB,KAAMwB,GAAMA,EAAE,QAAUF,GAAoBE,EAAE,OAAShD,CAAI,GAAG,QAAU,GACtG,EAEA,GAAI,CAAC6C,EACH,OAAOlB,EAGT,IAAMjI,EACJ8D,EAAQ,QAAQ,OAAQmF,GAAqB,iBAAkBA,CAAC,EAAE,KAAMA,GAAMA,EAAE,UAAY3C,CAAI,GAC/F,CACC,aAAc7B,GAAU,IACxB,SAAAwC,EACA,QAASX,EACT,OAAQ,UACR,KAAM,SACR,EAEI4C,EAAoB,CACxB,GAAGlJ,EACH,KAAMA,EAAM,aACZ,KAAM,CACJ,GAAGA,EACH,QAAS+H,CACX,EACA,GAAI,CACF,GAAG/H,EACH,QAASmJ,EAAU,KACrB,EACA,OAAQ,IAAIpE,GAAU,CAACwD,EAAWtB,EAAU,EAAE,EAAE,UAAU,CAC5D,EAEA,MAAO,CAAC,GAAGgB,EAAKiB,CAAQ,CAC1B,CAGA,OAAOjB,CACT,EAAG,CAAC,CAAc,EAEZsB,EAAiBC,GAAsB3D,EAAWrD,EAAcsF,EAAMhE,EAASsE,EAAWL,CAAU,EAE1G,OAAIwB,GACFnB,EAAU,KAAKmB,CAAc,EAGxBnB,CACT,EAEMoB,GAAwB,CAC5B3D,EACArD,EACA,CAAE,QAAAiH,EAAS,YAAAzB,EAAa,aAAA0B,CAAa,EACrC5F,EACA6F,EAA0B,CAAC,EAC3B5B,IACmB,CAEnB,GAAIvF,IAAiB,GAAI,CAKvB,GAAImH,EAAa,OAAS,GAAK5B,GACT4B,EAAa,KAAMT,GAAaA,EAAS,IAAI,UAAYnB,CAAU,EAEtE,CAEf,IAAM6B,EAAkB/D,EAAU,UAAWgE,GAASA,IAAS9B,CAAU,EAEzE,GAAI6B,IAAoB,GAAI,CAE1B,IAAME,EAAmB9B,EAAY4B,CAAe,EAE9CG,EADoBL,EAAaE,CAAe,EACTE,EAG7C,GAAIC,GAAoB,EAAG,CACzB,IAAMC,EAAW,KAAK,IAAID,CAAgB,EAAIN,EAG9C,GAAIO,EAAWP,EAAS,CACtB,IAAMQ,EAAO,IAAIlF,GAAUiF,EAAUlG,EAAQ,aAAa,SAAU,EAAE,EAIhEoG,GADeR,EAAa,IAAI,CAAC9F,GAAG/F,IAAM+F,GAAIoE,EAAYnK,CAAC,CAAE,EAC1B,OACvC,CAACsM,GAAKC,EAAMvM,KACNA,KAAM+L,GAAmBQ,EAAOD,GAAI,QAAUC,EAAO,EAChD,CAAE,MAAOvM,GAAG,OAAQuM,CAAK,EAE3BD,GAET,CAAE,MAAO,EAAG,OAAQ,CAAE,CACxB,EAEA,MAAO,CACL,OAAQF,EAAK,UAAU,EACvB,KAAM,CACJ,QAASlC,CACX,EACA,GAAI,CACF,QAASlC,EAAUqE,GAAoB,KAAK,CAC9C,EACA,KAAMpG,EAAQ,aAAa,KAC3B,OAAQA,EAAQ,aAAa,OAC7B,KAAMW,GAAU,MAClB,CACF,CACF,CACF,CACF,CAGF,OAAO,IACT,CAEA,IAAMY,EAAUQ,EAAUrD,CAAY,EAChCsH,EAAmB9B,EAAYxF,CAAY,EAE3CuH,EADoBL,EAAalH,CAAY,EACNsH,EACvCO,EAAeX,EAAa,IAAI,CAAC9F,EAAG/F,IAAM+F,EAAIoE,EAAYnK,CAAC,CAAE,EAG7DyM,EAAgBX,EAAa,OAAS,EAExCY,EAAuBR,IAAqB,EAAIA,EAAmBN,EAAU,EAC7Ee,EAAaD,EAAuB,EACpCE,EAAoB,EAIpBC,EAAiB,GACrB,GAAIJ,GAAiB9H,IAAiB,GAAKuF,EAAY,CACrD,IAAM4C,EAAchB,EAAa,KAAMT,GAAaA,EAAS,IAAI,UAAYnB,CAAU,EACjF6C,EAAUjB,EAAa,KAAMT,GAAaA,EAAS,MAAM,UAAYnB,CAAU,EAIjF4C,GAAe,CAACC,IAClBJ,EAAa,GACbE,EAAiB,GAYjBD,EAVqBf,EAAa,IAAI,CAAC,EAAG7L,IAAM,EAAImK,EAAYnK,CAAC,CAAE,EAC1B,OACvC,CAACsM,EAAKC,EAAMvM,IACNA,IAAM2E,GAAgB4H,EAAOD,EAAI,QAAUC,EAAO,EAC7C,CAAE,MAAOvM,EAAG,OAAQuM,CAAK,EAE3BD,EAET,CAAE,MAAO,EAAG,OAAQ,CAAE,CACxB,EACwC,MAE5C,CAEA,GAAIG,GAAiBP,EAAmB,EAAG,CAGzC,IAAMc,EAAgBR,EAAa,OACjC,CAACF,EAAKC,EAAMvM,IACNA,IAAM2E,GAAgB4H,EAAOD,EAAI,OAC5B,CAAE,MAAOtM,EAAG,OAAQuM,CAAK,EAE3BD,EAET,CAAE,MAAO,EAAG,OAAQ,CAAE,CACxB,EAIIU,EAAc,OAASpB,EAAU,GAAK,CAACiB,IACzCH,EAAuBM,EAAc,OACrCL,EAAa,GACbC,EAAoBI,EAAc,MAEtC,MAAWP,GAAiBP,GAAoB,GAG1BJ,EAAa,KAAMT,GAAaA,EAAS,IAAI,UAAY7D,CAAO,IAKlFkF,EAAuB,KAAK,IAAIR,CAAgB,EAAIN,EACpDe,EAAa,GAabC,EAV4BJ,EAAa,OACvC,CAACF,EAAKC,EAAMvM,IACNA,IAAM2E,GAAgB4H,EAAOD,EAAI,QAAUC,EAAO,EAC7C,CAAE,MAAOvM,EAAG,OAAQuM,CAAK,EAE3BD,EAET,CAAE,MAAO,EAAG,OAAQ,CAAE,CACxB,EAEwC,OAI5C,GAAI,CAACI,EACH,OAAO,KAGT,IAAMN,EAAO,IAAIlF,GAAU,KAAK,IAAIwF,CAAoB,EAAGzG,EAAQ,aAAa,SAAU,EAAE,EAG5F,GAAI,CAACwG,EAAe,CAClB,IAAMQ,EAAqBT,EAAa,OACtC,CAAC,CAAE,MAAAU,EAAO,OAAAC,CAAO,EAAGzC,EAAW1K,IACzB0K,EAAYyC,EACP,CAAE,MAAOnN,EAAG,OAAQ0K,CAAU,EAEhC,CAAE,MAAAwC,EAAO,OAAAC,CAAO,EAEzB,CAAE,MAAO,EAAG,OAAQX,EAAa,CAAC,CAAG,CACvC,EACAI,EAAoBD,EAAa,EAAIM,EAAmB,KAC1D,CAIA,IAAMG,EAAsBpF,EAAU4E,CAAiB,EACjDS,EAAcV,EAAaS,GAAuB5F,EAAU0C,GAAc1C,EAC1E8F,EAAYX,EAAazC,GAAc1C,EAAU4F,GAAuBlD,GAAc1C,EAE5F,MAAO,CACL,OAAQ4E,EAAK,UAAU,EACvB,KAAM,CACJ,QAASiB,CACX,EACA,GAAI,CACF,QAASC,CACX,EACA,KAAMrH,EAAQ,aAAa,KAC3B,OAAQA,EAAQ,aAAa,OAC7B,KAAMW,GAAU,MAClB,CACF,ECxVA,OAAS,WAAW2G,OAA0C,cCAvD,IAAMC,GAAkB1O,GAC7BA,EAAO,SAAW,YCDb,SAAS2O,GAAyCjD,EAAQ,CAC/D,OAAQkD,GAA2D,EAAQA,EAAMlD,CAAG,CACtF,CFWO,IAAMmD,GAAyB,MAAO,CAC3C,QAAA1H,EACA,QAAAuB,EACA,YAAA7G,CACF,IAIqC,CACnC,IAAMiN,EAAWpI,EAAY,CAAE,UAAW,EAAQS,EAAQ,UAAY,YAAAtF,CAAY,CAAC,EAI7EkN,GADyB,MAAMD,EAAS,wBAAwBL,GAAW/F,CAAO,EAAG,CAAE,MAAO,EAAG,CAAC,EAAE,KAAK,GACjE,IAAKsG,GAAQA,EAAI,SAAS,EAGpEC,EAAgBF,EACpB,GAAI,CACF,IAAM3F,EAAiB,IAAIX,EAAe,CAAE,YAAA5G,CAAY,CAAC,EACnDqN,EAAclG,EAAe7B,CAAO,EACpCgI,EAAkB,MAAM/F,EAAe,aAAa,CAAE,QAAAV,EAAS,QAASwG,CAAY,CAAC,EAE3F,GAAI,cAAeC,EAAiB,CAElC,IAAMC,EAAYD,EAAgB,UAAU,OAAO,IAAK9L,GAAUA,EAAM,sBAAsB,EACxFgM,EAAUF,EAAgB,UAAU,KAAK,IAAKG,GAAQA,EAAI,sBAAsB,EAIhFC,EAHe,CAAC,GAAGH,EAAW,GAAGC,CAAO,EAGJ,IAAI,MAAOG,GAAe,CAClE,GAAI,CAIF,OAH2B,MAAMV,EAC9B,wBAAwBL,GAAWe,CAAU,EAAG,CAAE,MAAO,EAAG,CAAC,EAC7D,KAAK,GACkB,IAAKR,GAAQA,EAAI,SAAS,CACtD,OAAS7G,EAAO,CACd,eAAQ,MAAM,oCAAqCqH,EAAYrH,CAAK,EAC7D,CAAC,CACV,CACF,CAAC,EAGKsH,GADsB,MAAM,QAAQ,WAAWF,CAAoB,GAEtE,OAAOb,EAAW,EAClB,IAAK1O,GAAWA,EAAO,KAAK,EAC5B,KAAK,EAGRiP,EAAgB,MAAM,KAAK,IAAI,IAAI,CAAC,GAAGF,EAAgB,GAAGU,CAAa,CAAC,CAAC,CAC3E,CACF,OAAStH,EAAO,CACd,QAAQ,MAAM,mCAAoCA,CAAK,CACzD,CAUA,OAPoB,MAAM,QAAQ,WAChC8G,EAAc,IAAI,MAAOD,IAAS,CAChC,OAAQA,EAAI,SAAS,EACrB,GAAI,MAAMF,EAAS,eAAeE,EAAK,CAAE,SAAU,OAAQ,+BAAgC,CAAE,CAAC,EAAE,KAAK,CACvG,EAAE,CACJ,GAGG,OAAON,EAAW,EAClB,IAAKgB,GAAOA,EAAG,KAAK,EACpB,OAAOf,GAAmB,IAAI,CAAC,CACpC,EG/EO,IAAMgB,GAAkB,CAACC,EAAgBC,IAAqB,CACnE,IAAMC,EAAeD,EAAU,IAAI,IAAIA,CAAO,EAAI,KAIlD,OAAIC,IACFA,EAAa,SAAW,OAAOF,CAAM,IAGhCE,GAAc,SAAS,GAAK,EACrC,ELGA,eAAsBC,GAAsB,CAC1C,QAAA5I,EACA,QAAAuB,EACA,YAAA7G,CACF,EAAkE,CAChE,OAAKsF,EAAQ,OAkFN,CACL,cA7EsB,MAAM0H,GAAuB,CAAE,QAAA1H,EAAS,QAAAuB,EAAS,YAAA7G,CAAY,CAAC,GAGnF,IAAI,CAAC,CAAE,OAAA+N,EAAQ,GAAAF,CAAG,IAAM,CACvB,GAAI,CAACA,EAAG,KACN,OAAO,KAGT,GAAM,CACJ,KAAAvE,EACA,YAAa,CAAE,QAAArC,CAAQ,CACzB,EAAI4G,EAGExG,EAAYJ,EAAQ,YAAY,IAAKwC,GAAQA,EAAI,SAAS,CAAC,EAC7DzF,EAAeqD,EAAU,QAAQR,CAAO,EACxCsH,EAA4BnK,IAAiB,GAG7C,CAACmK,GAA6B7E,EAAK,mBAEnCA,EAAK,iBAAiB,KAAMF,GAAYA,EAAQ,QAAUvC,CAAO,IAChEyC,EAAK,mBAAqB,CAAC,GAAG,KAAMF,GAAYA,EAAQ,QAAUvC,CAAO,KAE1EsH,EAA4B,GAE5BnK,EAAe,IAQnB,IAAMoK,EAAWpK,IAAiB,IAAMA,EAAeiD,EAAQ,OAAO,sBAEhE2C,EAAYP,GAChBhC,EACArD,EACA,CACE,QAASoK,EAAW,OAAO9E,EAAK,GAAG,EAAI,EACvC,YAAaA,EAAK,YAAY,IAAI,MAAM,EACxC,aAAcA,EAAK,aAAa,IAAI,MAAM,EAC1C,kBAAmBA,EAAK,kBAAoB,CAAC,GAAG,IAAIH,EAAoB,EACxE,mBAAoBG,EAAK,mBAAqB,CAAC,GAAG,IAAIH,EAAoB,CAC5E,EACA7D,CACF,EAEM+I,EAASC,GAAY1E,EAAW/C,CAAO,EAE7C,MAAO,CACL,KAAMkH,EAEN,OAAAM,EACA,QAAS,OAAOR,EAAG,KAAK,sBAAwB,GAAG,EACnD,OAAQjE,EAMR,KAAMA,EAAU,CAAC,GAAG,MAAM,SAAYvC,EAAU,CAAC,EACjD,GAAIuC,EAAU,CAAC,GAAG,IAAI,UAAYwE,EAAW,GAAKvH,GAClD,WAAYuH,EACZ,WAAY,CAACA,EACb,SAAUA,EACV,UAAW,OAAOP,EAAG,SAAS,EAAI,IAClC,eAAgB,GAChB,SAAU,OAAO,OAAOA,EAAG,KAAK,GAAG,EAAI,OAAOA,EAAG,KAAK,oBAAoB,CAAC,EAC3E,QAAS,OAAOvI,EAAQ,OAAO,EAC/B,aAAcwI,GAAgBC,EAAQzI,EAAQ,WAAW,CAC3D,CACF,CAAC,EACA,OAAWuI,GAAgCA,IAAO,IAAI,CAIzD,EAnFS,QAAQ,OAAO,CACpB,MAAOzQ,GAAU,cAAc,+BAA+B,CAChE,CAAC,CAkFL,CAEA,IAAMkR,GAAc,CAAC1E,EAAsB/C,IAAoB,CAE7D,GAAI+C,EAAU,SAAW,EACvB,OAAOV,EAAgB,QAIzB,IAAMqF,EAAe3E,EAAU,OAAQa,GAAMA,EAAE,MAAM,UAAY5D,GAAW4D,EAAE,IAAI,UAAY5D,CAAO,EAGrG,GAAI0H,EAAa,SAAW,EAC1B,OAAOrF,EAAgB,QAIzB,IAAMsF,EAAaD,EAAa,KAAM9D,GAAMA,EAAE,MAAM,UAAY5D,CAAO,EACjE4H,EAAeF,EAAa,KAAM9D,GAAMA,EAAE,IAAI,UAAY5D,CAAO,EAGvE,OAAI2H,GAAcC,EACTvF,EAAgB,KAIrBsF,EACKtF,EAAgB,KAIrBuF,EACKvF,EAAgB,QAGlBA,EAAgB,OACzB,EM3IA,OAAS,aAAA9L,OAAiB,uBAC1B,OACE,aAAAD,OAOK,2BACP,MAAkD,cCVlD,OACE,aAAAuR,OAMK,2BCPP,OAAS,aAAAA,MAA6B,2BAG/B,IAAMC,GAAoBrI,GAAuD,CACtF,GAAIA,GAAO,OAAS,mBAClB,OAAQA,EAAM,KAAM,CAClB,IAAK,6BACH,MAAO,CACL,KAAMoI,EAAU,QAChB,QAAS,CACP,MAAO,2CACP,YAAa,gEACf,CACF,CACJ,CAGF,MAAO,CACL,KAAMA,EAAU,QAChB,QAAS,CACP,MAAO,oCACP,YAAa,8EACf,CACF,CACF,EAEaE,GAAoB,CAC/B,CAACF,EAAU,OAAO,EAAG,CACnB,KAAMA,EAAU,QAChB,QAAS,CACP,MAAO,yBACP,YAAa,iDACf,CACF,EACA,CAACA,EAAU,MAAM,EAAG,CAClB,KAAMA,EAAU,OAChB,QAAS,CACP,MAAO,mBACP,YAAa,iDACb,aAAc,CACZ,OAAQ,qBACR,QAAS,gBACX,CACF,CACF,CACF,EC5CA,OAAS,iCAAAG,OAAqC,4BCCvC,SAASC,GAAqBC,EAA+B,CAClE,OAAOA,EAAM,IAAI,SAAW,GAAKA,EAAM,KAAK,SAAW,CACzD,CAEO,SAASC,GAAgBD,EAAmC,CACjE,OAAOA,GAAU,IACnB,CCRA,OAAS,aAAAxI,OAAiB,0BAE1B,OACE,6BAAA0I,GACA,+BAAAC,GACA,0BAAAC,GACA,qBAAAC,OACK,yBACP,OACE,2BAAAC,GACA,6BAAAC,GACA,yBAAAC,OAEK,cAIA,IAAMC,GAAwB,CACnCC,EACAC,EACAC,EACAC,IACyB,CACzB,GACE,CAACP,GAAwBI,EAAaN,EAAsB,GAC5D,CAACG,GAA0BG,CAAW,GACtC,CAACF,GAAsBE,CAAW,EAElC,OAAO,KAGT,GAAI,CAGF,GAF0BR,GAA0BQ,CAAW,IAErCL,GAAkB,YAC1C,OAAO,KAGT,GAAM,CAAE,SAAAS,EAAU,KAAA9O,CAAK,EAAImO,GAA4B,CACrD,GAAGO,EACH,KAAM,WAAW,KAAKA,EAAY,IAAI,CACxC,CAAC,EAGKK,EADaD,EAAS,OAAO,UAAYF,IACP,GAAO,OAAS,MAExD,OAAAD,EAAcI,CAAgB,EAAE,KAAK,CACnC,MAAO,CACL,GAAGF,EACH,QAAS,EACX,EACA,MAAO,CACL,CACE,aAAc,IAAIrJ,GAAUxF,EAAK,OAAQ6O,EAAa,SAAU,EAAE,EAAE,SAAS,EAC7E,SAAU,MACZ,CACF,CACF,CAAC,EAEM,CACL,MAAO,eACP,MAAO,CAAC9M,EAAY,OAAQ+M,EAAS,OAAO,OAAO,EAAG/M,EAAY,KAAM+M,EAAS,YAAY,OAAO,CAAC,CACvG,CACF,MAAQ,CACN,OAAO,IACT,CACF,EClEA,OAAS,aAAAtJ,OAAiB,0BAG1B,OACE,4BAAAwJ,GACA,4BAAAC,GACA,oBAAAC,GACA,mCAAAC,OACK,wBACP,OAAS,6BAAAZ,GAA2B,yBAAAC,OAA8D,cAIlG,IAAMY,GAA8B,MAAOlD,EAA0B0C,IAA6C,CAChH,GAAI,CACF,IAAMS,EAAsB,MAAMnD,EAAS,eAAe0C,EAAS,CAAE,SAAU,YAAa,CAAC,EAAE,KAAK,EAEpG,GAAI,MAAM,QAAQS,EAAoB,OAAO,IAAI,EAC/C,OAAO,KAGT,IAAMC,EAAOD,EAAoB,OAAO,KAAK,OAAO,KACpD,OAAO,OAAOC,GAAM,MAAS,SAAWA,EAAK,KAAO,IACtD,MAAQ,CACN,OAAO,IACT,CACF,EAEaC,GAAwB,MACnCrD,EACAwC,EACAC,EACAC,EACAY,IACkC,CAClC,GAAI,CAACA,GAAQ,QAAU,CAACjB,GAA0BG,CAAW,GAAK,CAACF,GAAsBE,CAAW,EAClG,OAAO,KAGT,GAAI,CACF,IAAMe,EAAmBR,GAAyBP,CAAW,EAE7D,GAAIe,IAAqBP,GAAiB,UAAYO,IAAqBP,GAAiB,gBAC1F,OAAO,KAGT,IAAMQ,EACJD,IAAqBP,GAAiB,gBAClCC,GACAH,GAEA,CAAE,SAAAF,EAAU,KAAA9O,CAAK,EAAI0P,EAAO,CAChC,GAAGhB,EACH,KAAM,WAAW,KAAKA,EAAY,IAAI,CACxC,CAAC,EACKiB,EAAY,MAAMP,GAA4BlD,EAAU4C,EAAS,OAAO,OAAO,EAErF,GAAI,CAACa,EACH,OAAO,KAGT,IAAMlP,EAAQ+O,EAAO,KAAM9F,GAAMA,EAAE,QAAQ,YAAY,IAAMiG,EAAU,YAAY,CAAC,EAEpF,GAAI,CAAClP,EACH,OAAO,KAIT,IAAMsO,GADaD,EAAS,OAAO,UAAYF,GAAWE,EAAS,UAAU,UAAYF,KACjD,GAAO,OAAS,MAClDlH,EAAW,aAAc1H,EAAOA,EAAK,SAAWS,EAAM,SAE5D,OAAAkO,EAAcI,CAAgB,EAAE,KAAK,CACnC,MAAAtO,EACA,MAAO,CACL,CACE,aAAc,IAAI+E,GAAUxF,EAAK,OAAQ0H,EAAU,EAAE,EAAE,SAAS,EAChE,SAAU,MACZ,CACF,CACF,CAAC,EAEM,CACL,MAAO,YAAYjH,EAAM,MAAM,GAC/B,MAAO,CAACsB,EAAY,OAAQ+M,EAAS,OAAO,OAAO,EAAG/M,EAAY,KAAM+M,EAAS,YAAY,OAAO,CAAC,CACvG,CACF,MAAQ,CACN,OAAO,IACT,CACF,EH9EO,IAAMc,GAAmB,MAC9BC,EACAjB,EACArK,EACA2H,IACG,CACH,IAAM4D,EAAc,MAAMhC,GAA8B+B,EAAc3D,CAAQ,EACxEyC,EAA+B,CACnC,IAAK,CAAC,EACN,KAAM,CAAC,CACT,EAEMoB,EAAU,MAAM,QAAQ,WAC5BD,EAAY,aAAa,IAAI,MAAOpB,GAEhCD,GAAsBC,EAAaC,EAAeC,EAASrK,EAAQ,YAAY,GAC9E,MAAMgL,GAAsBrD,EAAUwC,EAAaC,EAAeC,EAASrK,EAAQ,MAAoB,GACxG,IAEH,CACH,EAAE,KAAMyL,GACNA,EACG,OAAOlE,EAAW,EAClB,IAAK1O,GAAWA,EAAO,KAAK,EAC5B,OAAO6Q,EAAY,CACxB,EAEA,MAAO,CACL,cAAAU,EACA,QAAAoB,CACF,CACF,EIxCA,OACE,aAAA7K,OAMK,2BAOA,IAAM+K,GAAuB,CAClCrB,EACAsB,EACA3L,IACuE,CACvE,IAAM4L,EAAmBD,EAAiB,gBAAgB,qBAAuB,CAAC,EAE5EE,EAA6C,CAAC,EAC9CC,EAA8C,CAAC,EAE/CC,EAAmC,OAAO,KAAKJ,EAAiB,aAAe,CAAC,CAAC,EAAE,OACtFpH,GAAQA,IAAQ8F,CACnB,EAEA,OAAAuB,EAAiB,QAAQ,CAAC,CAAE,MAAAI,EAAO,GAAIC,EAAS,IAAKC,CAAS,IAAM,CAClE,IAAMhQ,EAAQiQ,GAAwBH,EAAOhM,CAAO,EAEpD,GAAI,CAAC9D,EACH,OAGF,IAAMkQ,EAAa,YAAalQ,EAAQA,EAAM,QAAUA,EAAM,OAE1D+P,IACGJ,EAAgBO,CAAU,IAC7BP,EAAgBO,CAAU,EAAI,CAC5B,MAAAlQ,EACA,MAAO,CAAC,CACV,GAGF2P,EAAgBO,CAAU,EAAE,MAAM,KAAK,CACrC,aAAc,OAAOH,EAAQ,KAAK,EAClC,SAAU,OAAOA,EAAQ,WAAc,SAAW,OAAOA,EAAQ,SAAS,EAAI,MAChF,CAAC,GAGCC,IACGJ,EAAiBM,CAAU,IAC9BN,EAAiBM,CAAU,EAAI,CAC7B,MAAAlQ,EACA,MAAO,CAAC,CACV,GAEF4P,EAAiBM,CAAU,EAAE,MAAM,KAAK,CACtC,aAAc,OAAOF,EAAS,KAAK,EACnC,SAAU,OAAOA,EAAS,WAAc,SAAW,OAAOA,EAAS,SAAS,EAAI,MAClF,CAAC,EAEL,CAAC,EAEM,CACL,cAAe,CACb,IAAK,OAAO,OAAOL,CAAe,EAClC,KAAM,OAAO,OAAOC,CAAgB,CACtC,EACA,uBAAAC,CACF,CACF,EAEMM,GACJL,IAEO,CACL,KAAMA,EAAM,KACZ,OAAQA,EAAM,KACd,SAAUA,EAAM,SAChB,YAAa,GACb,QAASA,EAAM,MAAQ,MACzB,GAGIM,GAA2B,CAC/BN,EACAhM,KACc,CACd,KAAMW,GAAU,IAChB,QAASqL,EAAM,QACf,QAAShM,EAAQ,QAAU,GAC3B,aAAcW,GAAU,IACxB,SAAUqL,EAAM,SAChB,KAAMA,EAAM,KACZ,OAAQA,EAAM,OACd,QAASA,EAAM,MAAQ,MACzB,GAEMG,GAA0B,CAACH,EAA8BhM,IACzDgM,EAAM,OAAS,QACVM,GAAyBN,EAAOhM,CAAO,EAG5CgM,EAAM,OAAS,OAASA,EAAM,OAAS,MAClCK,GAA0BL,CAAK,EAGjC,KC9GT,MAAqB,mBACrB,OAAS,UAAA1N,GAAQ,UAAAiO,OAAc,cAIxB,IAAMC,GAAwB,MAAO,CAC1C,OAAA7R,EACA,QAAA8R,EACA,SAAAC,CACF,IAAoF,CAClF,GAAI,CACF,OAAO,MAAMA,EAAS,OAAO,QAAQ,KAAK,CACxC,MAAO/R,EAAO,MACd,QAAS,CAAC,aAAc,YAAY,EACpC,SAAU,SACV,SAAU,CACR,IAAK8R,CACP,EACA,aAAc,CAAC9R,EAAO,iBAAiB,EAEvC,gBAAiB4R,GAAO,OAAOjO,GAAO,OAAO3D,EAAO,OAAO,CAAC,CAC9D,CAAC,CACH,OAAS7B,EAAK,CACZ,eAAQ,MAAM,8BAA+BA,CAAG,EACzC,IACT,CACF,EPPO,IAAM6T,GAAqB,MAAO,CACvC,iBAAAC,EACA,QAAA5M,EACA,SAAA2H,CACF,IAI2E,CACzE,GAAM,CAAE,OAAAhN,CAAO,EAAIiS,EACbC,EAAe,MAAML,GAAsBI,CAAgB,EAC3D,CAAE,WAAAE,EAAY,WAAAC,CAAW,EAAIF,GAAc,QAAU,CAAC,EACtDG,EAAgC,CACpC,MAAO,sBACP,MAAO,CAACtP,GAAS,WAAYkP,EAAiB,OAAO,iBAAiB,CAAC,CACzE,EACMpB,EAA2B,CAACwB,CAAc,EAE5CC,EAAyB,GACzB7C,EACA8C,EAUJ,GARI,CAACH,GAAcA,EAAW,cAAgB,UAC5CG,EAAQ5D,GAAkBF,GAAU,OAAO,EAClC2D,EAAW,cAAgB,YACpCG,EAAQ5D,GAAkBF,GAAU,MAAM,EACjCyD,GAAc,gBACvBK,EAAQ7D,GAAiBwD,EAAa,aAAa,GAGjDC,EAAY,CACd,GAAM,CAAE,cAAeK,EAAwB,uBAAApB,CAAuB,EAAIL,GACxE/Q,EAAO,QACPmS,EACA9M,CACF,EAEA,GADAoK,EAAgB+C,EACZpB,EAAuB,OAAS,EAAG,CAErC,IAAMqB,EAAoBN,EAAW,gBAAgB,oBAC/CO,EAAiBD,GAAmB,OAAQpB,GAAUA,EAAM,KAAOA,EAAM,IAAI,UAAY,CAAC,GAAK,CAAC,EAChGsB,EAAiBF,GAAmB,OAAQpB,GAAUA,EAAM,IAAMA,EAAM,GAAG,UAAY,CAAC,GAAK,CAAC,EAGrFqB,EAAe,OAAS,GAAKC,EAAe,OAAS,GAKlEN,EAAe,MAAM,KAAKxP,EAAY,UAAW7C,EAAO,OAAO,CAAC,EAChEqS,EAAe,MAAM,KAAKvP,GAAgB,mBAAoBsO,CAAsB,CAAC,IAGrFiB,EAAe,MAAM,KACnBxP,EAAYuO,EAAuB,SAAW,EAAI,OAAS,UAAWpR,EAAO,OAAO,CACtF,EACAqS,EAAe,MAAM,KACnBjB,EAAuB,SAAW,EAC9BvO,EAAY,KAAMuO,EAAuB,CAAC,CAAE,EAC5CtO,GAAgB,mBAAoBsO,CAAsB,CAChE,EAEJ,MAEEiB,EAAe,MAAM,KAAKxP,EAAY,UAAW7C,EAAO,OAAO,CAAC,EAGlEsS,EAAyB,EAC3B,KAAO,CAEL,GAAM,CAAE,cAAeM,EAAqB,QAASC,CAAc,EAAI,MAAMnC,GAC3E1Q,EAAO,kBACPA,EAAO,QACPqF,EACA2H,CACF,EACAyC,EAAgBmD,EAChB/B,EAAQ,KAAK,GAAGgC,CAAa,CAC/B,CAEA,MAAO,CACL,uBAAAP,EACA,QAAAzB,EACA,MAAA0B,EACA,cAAA9C,CACF,CACF,EQvGA,OAAS,aAAAqD,OAAiB,cCA1B,IAAMC,GAAsB,8BAErB,SAASC,GAA4B3N,EAAkB4N,EAAcC,EAA6B,KAAM,CAC7G,GAAI,CAEF,IAAMnF,EAAU1I,EAAQ,YAAc,IAAI,IAAIA,EAAQ,WAAW,EAAI,IAAI,IAAI0N,EAAmB,EAChG,OAAAhF,EAAQ,UAAY,GAAGmF,CAAQ,IAAID,CAAI,GAChClF,EAAQ,SAAS,CAC1B,MAAQ,CACN,MAAO,GAAG1I,EAAQ,WAAW,IAAI6N,CAAQ,IAAID,CAAI,EACnD,CACF,CDRA,IAAME,GAAmB,IACnBC,GAAc,GAYPC,GAAiC,MAAO,CACnD,SAAArG,EACA,OAAAc,EACA,mBAAA7J,EACA,QAAAqP,EACA,QAAAjO,EACA,WAAAkO,EAAa,YACb,WAAA5V,EAAayV,EACf,IAA8D,CAC5D,IAAIrV,EAAU,EACVyV,EAA4B,KAC1BxF,EAAegF,GAA4B3N,EAASyI,EAAQ,IAAI,EAEtE,KAAO/P,EAAUJ,GACf,GAAI,CACF,IAAMsB,EAAW,MAAM+N,EACpB,qBAAqB,CAAC8F,GAAUhF,CAAM,CAAC,EAAG,CAAE,yBAA0B,EAAK,CAAC,EAC5E,KAAK,EAER,GAAI,CAAC7O,GAAU,QAAQ,CAAC,EAAG,CACzB,MAAM,IAAI,QAASwU,GAAY,WAAWA,EAASN,EAAgB,CAAC,EACpEpV,IACA,QACF,CAEA,GAAM,CAAE,mBAAA2V,EAAoB,IAAAvV,CAAI,EAAIc,EAAS,MAAM,CAAC,EAEpD,GAAId,EACF,eAAQ,MAAM,uDAAwDA,CAAG,EACzE8F,EAAmB,sBAAsB,CAAE,OAAA6J,EAAQ,QAAAwF,CAAQ,CAAC,EACrD,GAGT,GAAII,GAAsBA,IAAuBF,IAC/CA,EAAaE,EAETA,IAAuB,aACzBzP,EAAmB,qBAAqB,CAAE,OAAA6J,EAAQ,QAAAwF,CAAQ,CAAC,EAI1DC,IAAe,aAAeG,IAAuB,aACrDH,IAAe,aAAe,CAAC,YAAa,WAAW,EAAE,SAASG,CAAkB,GACpFH,IAAe,aAAeG,IAAuB,aAGtD,OAAAzP,EAAmB,uBAAuB,CAAE,OAAA6J,EAAQ,QAAAwF,EAAS,aAAAtF,CAAa,CAAC,EACpE,GAIX,MAAM,IAAI,QAASyF,GAAY,WAAWA,EAASN,EAAgB,CAAC,EACpEpV,GACF,OAASsI,EAAO,CACd,GAAIA,aAAiB,OAASA,EAAM,QAAQ,SAAS,oBAAoB,EACvE,eAAQ,MAAM,gEAAgE,EAC9EpC,EAAmB,sBAAsB,CAAE,OAAA6J,EAAQ,QAAAwF,CAAQ,CAAC,EACrD,GAET,MAAM,IAAI,QAASG,GAAY,WAAWA,EAASN,EAAgB,CAAC,EACpEpV,GACF,CAIF,OAAIyV,IAAe,aAAeA,IAAe,aAC/CvP,EAAmB,uBAAuB,CAAE,OAAA6J,EAAQ,QAAAwF,EAAS,aAAAtF,CAAa,CAAC,EACpE,KAGT/J,EAAmB,sBAAsB,CAAE,OAAA6J,EAAQ,QAAAwF,CAAQ,CAAC,EACrD,GACT,EE1FA,OAAS,KAAAlT,MAAS,MAElB,IAAMuT,GAAoBvT,EAAE,OAAO,CACjC,QAASA,EAAE,OAAO,EAClB,aAAcA,EAAE,OAAO,EAAE,OAAO,EAChC,YAAaA,EACV,OAAO,CACN,oBAAqBA,EAAE,KAAK,CAAC,YAAa,YAAa,WAAW,CAAC,EAAE,SAAS,EAC9E,WAAYA,EAAE,OAAO,EAAE,SAAS,EAChC,eAAgBA,EAAE,OAAO,EAAE,SAAS,EACpC,cAAeA,EAAE,QAAQ,EAAE,SAAS,CACtC,CAAC,EACA,SAAS,CACd,CAAC,EAEKwT,GAAexT,EAAE,MAAM,CAACuT,EAAiB,CAAC,EAEnCE,GAAsB7T,GAC1B4T,GAAa,UAAU5T,CAAM,EXE/B,IAAM8T,GAAyB,MAAO,CAC3C,QAAAR,EACA,QAAAjO,EACA,mBAAApB,EACA,YAAAlE,EACA,SAAAgS,CACF,IAMM,CACJ,GAAM,CAAE,OAAA/R,CAAO,EAAIsT,EACb,CAAE,KAAAxS,EAAM,QAAAiT,EAAS,MAAA1N,CAAM,EAAIwN,GAAmB7T,CAAM,EAE1D,GAAI,CAAC+T,EACH,eAAQ,MAAM,iBAAkB1N,CAAK,EAC9B,CACL,MAAOlJ,GAAU,cAAc,CAAE,QAAS,iCAAkC,KAAM,CAAE,MAAOkJ,CAAM,CAAE,CAAC,CACtG,EAGF,GAAM,CAAC,CAAE,QAAAqJ,EAAS,aAAAiB,EAAc,YAAAqD,CAAY,CAAC,EAAIlT,EAE3CkM,EAAWpI,EAAY,CAC3B,UAAW,EAAQS,EAAQ,UAC3B,YAAAtF,CACF,CAAC,EAEK,CAAE,QAAA8Q,EAAS,uBAAAyB,EAAwB,MAAAC,EAAO,cAAA9C,CAAc,EAAI,MAAMuC,GAAmB,CACzF,iBAAkB,CAChB,QAASsB,EAAQ,SAAS,IAC1B,OAAQ,CACN,QAAA5D,EACA,MAAOxI,EAAe7B,CAAO,EAC7B,kBAAmBsL,CACrB,EACA,SAAAoB,CACF,EACA,QAAA1M,EACA,SAAA2H,CACF,CAAC,EAEKiH,EAA2B,CAC/B,MAAO,mCACP,QAAS,CACP,QAAS5O,EAAQ,QACjB,KAAMA,EAAQ,UACd,QAASA,EAAQ,OACnB,EACA,QAAAwL,EACA,MAAA0B,EACA,cAAA9C,EACA,mBAAoB,GACpB,uBAAA6C,CACF,EAEM4B,EAA2B,CAC/B,KAAMhX,GAAU,iCAChB,QAAAwS,EACA,KAAMiB,CACR,EAEM1R,EAAW,MAAMgF,EAAmB,gBAAgB,CAAE,QAAAqP,EAAS,YAAAW,EAAa,YAAAC,CAAY,CAAC,EAE/F,GAAI,UAAWjV,EACb,MAAO,CACL,MAAOA,EAAS,KAClB,EAGF,IAAI6O,EAEJ,GAAI,CACF,OAAAA,EAAS,MAAMqG,GAAUnH,EAAU/N,EAAU+U,CAAW,EACxD,MAAM/P,EAAmB,qBAAqB,CAAE,OAAA6J,EAAQ,QAAAwF,CAAQ,CAAC,EAEjED,GAA+B,CAC7B,SAAArG,EACA,OAAAc,EACA,mBAAA7J,EACA,QAAAqP,EACA,QAAAjO,EACA,WAAY2O,GAAa,mBAC3B,CAAC,EAEM,CACL,OAAQlG,CACV,CACF,OAASzH,EAAO,CACd,eAAQ,MAAMA,CAAK,EAEZ,CACL,MAAOlJ,GAAU,SAAS,CAAE,QAAS,qBAAsB,KAAM,CAAE,MAAOkJ,CAAM,CAAE,CAAC,CACrF,CACF,CACF,EAEM8N,GAAY,MAChBnH,EACA/N,EACA+U,IAEI,WAAY/U,EACPA,EAAS,OAGG,MAAM+N,EACxB,gBAAgB/N,EAAS,WAA4C,CACpE,GAAG+U,EACH,SAAU,QACZ,CAAC,EACA,KAAK,EYrIV,OAAS,aAAA7W,OAAiB,uBAC1B,OACE,aAAAD,OAMK,2BCRP,OAAS,KAAAkD,OAAS,MAElB,IAAMuT,GAAoBvT,GAAE,OAAO,CACjC,QAASA,GAAE,OAAO,EAClB,aAAcA,GAAE,OAAO,EAAE,OAAO,CAClC,CAAC,EAEKwT,GAAexT,GAAE,MAAM,CAACuT,EAAiB,CAAC,EAEnCE,GAAsB7T,GAC1B4T,GAAa,UAAU5T,CAAM,EDQ/B,IAAMoU,GAAkB,MAAO,CACpC,QAAAd,EACA,QAAAjO,EACA,mBAAApB,EACA,YAAAlE,EACA,SAAAgS,CACF,IAMM,CACJ,GAAM,CAAE,OAAA/R,CAAO,EAAIsT,EACb,CAAE,KAAAxS,EAAM,QAAAiT,EAAS,MAAA1N,CAAM,EAAIwN,GAAmB7T,CAAM,EAE1D,GAAI,CAAC+T,EACH,eAAQ,MAAM,iBAAkB1N,CAAK,EAC9B,CACL,MAAOlJ,GAAU,cAAc,CAAE,QAAS,iCAAkC,KAAM,CAAE,MAAOkJ,CAAM,CAAE,CAAC,CACtG,EAGF,GAAM,CAAC,CAAE,QAAAqJ,EAAS,aAAAiB,CAAa,CAAC,EAAI7P,EAE9BkM,EAAWpI,EAAY,CAC3B,UAAW,EAAQS,EAAQ,UAC3B,YAAAtF,CACF,CAAC,EAEK,CAAE,QAAA8Q,EAAS,uBAAAyB,EAAwB,MAAAC,EAAO,cAAA9C,CAAc,EAAI,MAAMuC,GAAmB,CACzF,iBAAkB,CAChB,QAASsB,EAAQ,SAAS,IAC1B,OAAQ,CACN,QAAA5D,EACA,MAAOxI,EAAe7B,CAAO,EAC7B,kBAAmBsL,CACrB,EACA,SAAAoB,CACF,EACA,QAAA1M,EACA,SAAA2H,CACF,CAAC,EAEKiH,EAA2B,CAC/B,MAAO,mCACP,QAAS,CACP,QAAS5O,EAAQ,QACjB,KAAMA,EAAQ,UACd,QAASA,EAAQ,OACnB,EACA,QAAAwL,EACA,MAAA0B,EACA,cAAe9C,GAAiBZ,GAAqBY,CAAa,EAAI,OAAYA,EAClF,mBAAoB,GACpB,uBAAA6C,CACF,EAEM4B,EAA2B,CAC/B,KAAMhX,GAAU,wBAChB,QAAAwS,EACA,KAAMiB,CACR,EAEM1R,EAAW,MAAMgF,EAAmB,gBAAgB,CAAE,QAAAqP,EAAS,YAAAW,EAAa,YAAAC,CAAY,CAAC,EAE/F,MAAI,UAAWjV,EACN,CACL,MAAOA,EAAS,KAClB,EAGI,eAAgBA,EAMf,CAAE,OAAQA,EAAS,UAAW,EAL5B,CACL,MAAO9B,GAAU,eAAe,yBAAyB,CAC3D,CAIJ,EEjGA,OAAS,aAAAA,OAAiB,uBAC1B,OACE,aAAAD,OAMK,2BACP,OAAS,UAAA0U,OAAc,cCTvB,OAAS,UAAAA,OAAc,cACvB,OAAS,wCAAAyC,OAA4C,cAE9C,IAAMC,GAAsBC,GAAmC,CACpE,GAAI,CACF,IAAMC,EAAQ5C,GAAO,OAAO2C,CAAa,EAEzC,OADgBF,GAAqC,EAC7C,OAAOG,CAAK,EACb,EACT,MAAQ,CACN,MAAO,EACT,CACF,ECXA,OAAS,KAAApU,OAAS,MAElB,IAAMqU,GAAoBrU,GACvB,OAAO,CACN,QAASA,GAAE,OAAO,EAClB,kBAAmBA,GAAE,OAAO,EAAE,OAAO,CACvC,CAAC,EACA,OAAO,CAAC,CAAE,kBAAAsU,CAAkB,IAAM,CAACJ,GAAmBI,CAAiB,EAAG,CACzE,QAAS,yDACX,CAAC,EAEGd,GAAexT,GAAE,MAAM,CAACqU,EAAiB,CAAC,EAEnCZ,GAAsB7T,GAC1B4T,GAAa,UAAU5T,CAAM,EFA/B,IAAM2U,GAAc,MAAO,CAChC,QAAArB,EACA,QAAAjO,EACA,mBAAApB,CACF,IAIM,CACJ,GAAM,CAAE,OAAAjE,CAAO,EAAIsT,EACb,CAAE,KAAAxS,EAAM,QAAAiT,EAAS,MAAA1N,CAAM,EAAIwN,GAAmB7T,CAAM,EAE1D,GAAI,CAAC+T,EACH,eAAQ,MAAM,iBAAkB1N,CAAK,EAC9B,CACL,MAAOlJ,GAAU,cAAc,CAAE,QAAS,qCAAsC,KAAM,CAAE,MAAOkJ,CAAM,CAAE,CAAC,CAC1G,EAGF,GAAM,CAAC,CAAE,QAAAqJ,EAAS,kBAAAgF,CAAkB,CAAC,EAAI5T,EAEnC8T,EAAc,IAAI,YAClBX,EAA2B,CAC/B,MAAO,eACP,QAAS,CACP,QAAS5O,EAAQ,QACjB,KAAMA,EAAQ,UACd,QAASA,EAAQ,OACnB,EACA,SAAU,CACR,KAAMiO,EAAQ,SAAS,KACvB,OAAQ,GAAGA,EAAQ,SAAS,IAAI,+CAChC,QAASA,EAAQ,SAAS,IAC5B,EACA,QAAS,CACP,CACE,MAAO,kBACP,MAAO,CACLzQ,EAAY,UAAW6M,CAAO,EAC9BjN,GAAS,UAAWmS,EAAY,OAAOhD,GAAO,OAAO8C,CAAiB,CAAC,CAAC,EACxE3R,GAAS,wBAAyB2R,CAAiB,CACrD,CACF,CACF,EACA,mBAAoB,EACtB,EAEMR,EAA2B,CAC/B,KAAMhX,GAAU,oBAChB,QAAAwS,EACA,KAAMgF,CACR,EAEMzV,EAAW,MAAMgF,EAAmB,gBAAgB,CAAE,QAAAqP,EAAS,YAAAW,EAAa,YAAAC,CAAY,CAAC,EAE/F,MAAI,UAAWjV,EACN,CACL,MAAOA,EAAS,KAClB,EAGI,eAAgBA,EAMf,CAAE,OAAQA,EAAS,UAAW,EAL5B,CACL,MAAO9B,GAAU,eAAe,yBAAyB,CAC3D,CAIJ,EjDnDA,OAAO0X,OAAc,mBAhCrB,IAAApU,EAAAqU,EAAAC,GAAAC,EAmCaC,GAAN,KAAkC,CAMvC,YAAY,CAAE,mBAAAhR,EAAoB,YAAAR,EAAa,QAAAyR,EAAS,QAAAC,CAAQ,EAAsB,CALtFvU,EAAA,KAAAH,EAAA,QACAG,EAAA,KAAAkU,EAAA,QACAlU,EAAA,KAAAmU,GAAA,QACAnU,EAAA,KAAAoU,EAAA,QAGE,GAAM,CAAE,YAAAjV,CAAY,EAAIyD,GAAOC,CAAW,EAE1CtC,EAAA,KAAK4T,GAAWG,GAChB/T,EAAA,KAAKV,EAAeV,GACpBoB,EAAA,KAAK2T,EAAsB7Q,GAI3B3C,EAAA,KAAKb,GACLa,EAAA,KAAKwT,GACLxT,EAAA,KAAKyT,IACL5T,EAAA,KAAK6T,EAAY,IAAIH,GAAS,CAC5B,QAAS9U,EAAc,mBACvB,OAAQ4E,GACR,UAAWwQ,GAAS,UACpB,MAAOA,GAAS,KAClB,CAAC,EACH,CAEA,MAAM,YAAY9P,EAA2C,CAC3D,OAAOT,EAAY,CAAE,UAAW,EAAQS,EAAQ,UAAY,YAAa/D,EAAA,KAAKb,EAAa,CAAC,CAC9F,CAGA,YAAa,CACX,OAAO,QAAQ,QAAQ,CAAC,CAAC,CAC3B,CAEA,oBAAoBT,EAAmC,CACrD,OAAO8D,GAAoB9D,CAAM,CACnC,CAEA,cAAcA,EAA6B,CACzC,OAAOgE,GAAc,CACnB,GAAGhE,EACH,mBAAoBsB,EAAA,KAAKwT,EAC3B,CAAC,CACH,CAEA,YAAY9U,EAA2B,CACrC,IAAMqH,EAAe,IAAI3G,EAAa,CAAE,QAASV,EAAO,QAAS,YAAasB,EAAA,KAAKb,EAAa,CAAC,EAEjG,OAAO0G,GAAY,CACjB,GAAGnH,EACH,aAAAqH,EACA,YAAa/F,EAAA,KAAKb,EACpB,CAAC,CACH,CAEA,aAAc,CACZ,IAAMvC,EAASjB,GAAcmG,EAAY,EACzC,OAAOlF,EAAO,QAAUA,EAAO,KAAO,MACxC,CAEA,cAAcmH,EAA0B,CACtC,OAAOD,GAAcC,EAAS/D,EAAA,KAAKb,EAAY,CACjD,CAEA,sBAAsBT,EAA+B,CACnD,OAAOiO,GAAsB,CAC3B,QAASjO,EAAO,QAChB,QAASA,EAAO,QAChB,YAAasB,EAAA,KAAKb,EACpB,CAAC,CACH,CAEA,UAAU4E,EAAkB,CAC1B,OAAKA,EAAQ,OAINc,GAAU,CAAE,QAASd,EAAQ,OAAQ,YAAa/D,EAAA,KAAKb,EAAa,CAAC,EAHnE,QAAQ,OAAO,CAAE,MAAOtD,GAAU,cAAc,+BAA+B,CAAE,CAAC,CAI7F,CAGA,MAAM,aAAamW,EAAqBjO,EAAkB,CACxD,OAAQiO,EAAQ,OAAQ,CACtB,KAAKpW,GAAU,wBACb,OAAOkX,GAAgB,CACrB,mBAAoB9S,EAAA,KAAKwT,GACzB,YAAaxT,EAAA,KAAKb,GAClB,QAAA4E,EACA,QAAAiO,EACA,SAAUhS,EAAA,KAAK0T,EACjB,CAAC,EAEH,KAAK9X,GAAU,iCACb,OAAO4W,GAAuB,CAC5B,mBAAoBxS,EAAA,KAAKwT,GACzB,YAAaxT,EAAA,KAAKb,GAClB,QAAA4E,EACA,QAAAiO,EACA,SAAUhS,EAAA,KAAK0T,EACjB,CAAC,EAEH,KAAK9X,GAAU,oBACb,OAAOyX,GAAY,CACjB,mBAAoBrT,EAAA,KAAKwT,GACzB,QAAAzP,EACA,QAAAiO,CACF,CAAC,CAEL,CACA,MAAO,CAAE,MAAOnW,GAAU,mBAAmB,UAAUmW,EAAQ,MAAM,gBAAgB,CAAE,CACzF,CACF,EA/GE7S,EAAA,YACAqU,EAAA,YACAC,GAAA,YACAC,EAAA","sourcesContent":["import {\n parseManifest,\n RpcMethod,\n type AppInfo,\n type ApprovalController,\n type BuildDerivationPathParams,\n type ConstructorParams,\n type DeriveAddressParams,\n type GetBalancesParams,\n type GetTransactionHistory,\n type Module,\n type Network,\n type NetworkFeeParam,\n type RpcRequest,\n} from '@avalabs/vm-module-types';\nimport type { SolanaProvider } from '@avalabs/core-wallets-sdk';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\nimport { TokenService } from '@internal/utils';\n\nimport ManifestJson from '../manifest.json';\nimport { getEnv } from './env';\nimport { deriveAddress } from './handlers/derive-address';\nimport { buildDerivationPath } from './handlers/build-derivation-path';\nimport { getNetworkFee } from './handlers/get-network-fee';\nimport { getTokens } from './handlers/get-tokens';\nimport { getBalances } from './handlers/get-balances';\nimport { getProvider } from './utils/get-provider';\nimport { getTransactionHistory } from './handlers/get-transaction-history';\nimport { signAndSendTransaction } from './handlers/sign-and-send-transaction';\nimport { signTransaction } from './handlers/sign-transaction';\nimport { signMessage } from './handlers/sign-message';\nimport Blockaid from '@blockaid/client';\nimport { BLOCKAID_API_KEY } from './constants';\n\nexport class SvmModule implements Module {\n #proxyApiUrl: string;\n #approvalController: ApprovalController;\n #appInfo: AppInfo;\n #blockaid: Blockaid;\n\n constructor({ approvalController, environment, appInfo, runtime }: ConstructorParams) {\n const { proxyApiUrl } = getEnv(environment);\n\n this.#appInfo = appInfo;\n this.#proxyApiUrl = proxyApiUrl;\n this.#approvalController = approvalController;\n\n // Temporarily referencing those props here just to silence eslint,\n // as eslint-disable-... comments don't seem to work on class properties.\n this.#proxyApiUrl;\n this.#approvalController;\n this.#appInfo;\n this.#blockaid = new Blockaid({\n baseURL: proxyApiUrl + '/proxy/blockaid/',\n apiKey: BLOCKAID_API_KEY,\n httpAgent: runtime?.httpAgent,\n fetch: runtime?.fetch,\n });\n }\n\n async getProvider(network: Network): Promise<SolanaProvider> {\n return getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl: this.#proxyApiUrl });\n }\n\n // TODO\n getAddress() {\n return Promise.resolve({});\n }\n\n buildDerivationPath(params: BuildDerivationPathParams) {\n return buildDerivationPath(params);\n }\n\n deriveAddress(params: DeriveAddressParams) {\n return deriveAddress({\n ...params,\n approvalController: this.#approvalController,\n });\n }\n\n getBalances(params: GetBalancesParams) {\n const tokenService = new TokenService({ storage: params.storage, proxyApiUrl: this.#proxyApiUrl });\n\n return getBalances({\n ...params,\n tokenService,\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getManifest() {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(network: NetworkFeeParam) {\n return getNetworkFee(network, this.#proxyApiUrl);\n }\n\n getTransactionHistory(params: GetTransactionHistory) {\n return getTransactionHistory({\n network: params.network,\n address: params.address,\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getTokens(network: Network) {\n if (!network.caipId) {\n return Promise.reject({ error: rpcErrors.invalidParams(`Network must have a CAIP-2 id`) });\n }\n\n return getTokens({ caip2Id: network.caipId, proxyApiUrl: this.#proxyApiUrl });\n }\n\n // TODO\n async onRpcRequest(request: RpcRequest, network: Network) {\n switch (request.method) {\n case RpcMethod.SOLANA_SIGN_TRANSACTION: {\n return signTransaction({\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n network,\n request,\n blockaid: this.#blockaid,\n });\n }\n case RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION: {\n return signAndSendTransaction({\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n network,\n request,\n blockaid: this.#blockaid,\n });\n }\n case RpcMethod.SOLANA_SIGN_MESSAGE: {\n return signMessage({\n approvalController: this.#approvalController,\n network,\n request,\n });\n }\n }\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n}\n","import {\n VsCurrencyType,\n getBasicCoingeckoHttp,\n simplePrice,\n simpleTokenPrice,\n type SimplePriceParams,\n} from '@avalabs/core-coingecko-sdk';\nimport type { Storage, RawSimplePriceResponse, SimplePriceResponse } from '@avalabs/vm-module-types';\nimport { coingeckoRetry } from '../../utils/coingecko-retry';\nimport { arrayHash } from '../../utils/array-hash';\nimport { CoingeckoProxyClient } from './coingecko-proxy-client';\nimport { WatchlistProxyClient } from './watchlist-proxy-client';\n\nconst coingeckoBasicClient = getBasicCoingeckoHttp();\n\nexport class TokenService {\n #storage?: Storage;\n #proxyApiUrl: string;\n\n constructor({ storage, proxyApiUrl }: { proxyApiUrl: string; storage?: Storage }) {\n this.#storage = storage;\n this.#proxyApiUrl = proxyApiUrl;\n }\n\n async getWatchlistDataForToken({\n tokenDetails,\n currency = VsCurrencyType.USD,\n }: {\n tokenDetails: {\n symbol: string;\n isNative: boolean;\n caip2Id: string;\n address?: string;\n };\n currency: VsCurrencyType;\n }): Promise<{\n priceInCurrency: number;\n change24: number;\n marketCap: number;\n vol24: number;\n }> {\n const data = (\n await new WatchlistProxyClient(this.#proxyApiUrl).watchlistToken({\n tokens: tokenDetails.symbol,\n currency: currency,\n })\n ).filter((token) => {\n return tokenDetails.isNative\n ? token.internalId === `NATIVE-${tokenDetails.symbol.toLowerCase()}`\n : token.platforms[tokenDetails.caip2Id] === tokenDetails.address;\n });\n\n const tokenInfo = data[0];\n\n if (!tokenInfo) {\n return {\n priceInCurrency: 0,\n change24: 0,\n marketCap: 0,\n vol24: 0,\n };\n }\n\n return {\n priceInCurrency: tokenInfo.current_price ?? 0,\n change24: tokenInfo.price_change_percentage_24h ?? 0,\n marketCap: tokenInfo.market_cap ?? 0,\n vol24: tokenInfo.total_volume ?? 0,\n };\n }\n\n /**\n * Get token price with market data first on coingecko (free tier) directly,\n * if we get 429 error, retry it on coingecko proxy (paid service)\n * @returns token price with market data\n */\n async getSimplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n }: SimplePriceParams): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = coinIds ? `${arrayHash(coinIds)}-${currencies.toString()}` : `${currencies.toString()}`;\n\n const cacheId = `getSimplePrice-${key}`;\n\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data) return data;\n\n try {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.simplePrice({\n coinIds,\n currencies,\n marketCap: true,\n vol24: true,\n change24: true,\n useCoingeckoProxy,\n }),\n );\n } catch {\n data = undefined;\n }\n this.#storage?.set?.(cacheId, data);\n return data;\n }\n\n /**\n * Get token price with market data for a list of addresses\n * @param tokenAddresses the token addresses\n * @param assetPlatformId The platform id for all the tokens in the list\n * @param currency the currency to be used\n * @returns a list of token price with market data\n */\n async getPricesByAddresses(\n tokenAddresses: string[],\n assetPlatformId: string,\n currency: VsCurrencyType = VsCurrencyType.USD,\n ): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = `${arrayHash(tokenAddresses)}-${assetPlatformId}-${currency}`;\n\n const cacheId = `getPricesWithMarketDataByAddresses-${key}`;\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data) return data;\n\n try {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency,\n useCoingeckoProxy,\n }),\n );\n } catch (err) {\n console.error(err);\n data = undefined;\n }\n this.#storage?.set?.(cacheId, data);\n return data;\n }\n\n private async fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency = VsCurrencyType.USD,\n useCoingeckoProxy = false,\n }: {\n assetPlatformId: string;\n tokenAddresses: string[];\n currency: VsCurrencyType;\n useCoingeckoProxy?: boolean;\n }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n const rawData = await new CoingeckoProxyClient(this.#proxyApiUrl).simplePriceByContractAddresses({\n id: assetPlatformId,\n contract_addresses: tokenAddresses,\n vs_currencies: [currency],\n include_market_cap: true,\n include_24hr_vol: true,\n include_24hr_change: true,\n });\n return this.transformSimplePriceResponse(rawData, [currency]);\n }\n\n return simpleTokenPrice(coingeckoBasicClient, {\n assetPlatformId,\n tokenAddresses,\n currencies: [currency],\n marketCap: true,\n vol24: true,\n change24: true,\n });\n }\n\n private async simplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n marketCap = false,\n vol24 = false,\n change24 = false,\n lastUpdated = false,\n useCoingeckoProxy = false,\n shouldThrow = true,\n }: SimplePriceParams & { useCoingeckoProxy?: boolean }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n const rawData = await new CoingeckoProxyClient(this.#proxyApiUrl).simplePrice({\n ids: coinIds,\n vs_currencies: currencies,\n include_market_cap: marketCap,\n include_24hr_vol: vol24,\n include_24hr_change: change24,\n include_last_updated_at: lastUpdated,\n });\n return this.transformSimplePriceResponse(rawData, currencies);\n }\n return simplePrice(coingeckoBasicClient, {\n coinIds,\n currencies,\n marketCap,\n vol24,\n change24,\n lastUpdated,\n shouldThrow,\n });\n }\n\n private transformSimplePriceResponse = (\n data: RawSimplePriceResponse,\n currencies = [VsCurrencyType.USD],\n ): SimplePriceResponse => {\n const formattedData: SimplePriceResponse = {};\n Object.keys(data).forEach((id) => {\n const tokenData = data[id];\n formattedData[id] = {};\n currencies.forEach((currency: VsCurrencyType) => {\n formattedData[id] = {\n [currency]: {\n price: tokenData?.[currency],\n change24: tokenData?.[`${currency}_24h_change`],\n vol24: tokenData?.[`${currency}_24h_vol`],\n marketCap: tokenData?.[`${currency}_market_cap`],\n },\n };\n });\n });\n return formattedData;\n };\n}\n","const DEFAULT_MAX_RETRIES = 10;\n\ntype RetryParams<T> = {\n operation: (retryIndex: number) => Promise<T>;\n isSuccess: (result: T) => boolean;\n maxRetries?: number;\n backoffPolicy?: RetryBackoffPolicyInterface;\n};\n/*\n * Retries an operation with defined backoff policy.\n *\n * @param operation - The operation to retry.\n * @param isSuccess - The predicate to check if the operation succeeded.\n * @param maxRetries - The maximum number of retries.\n * @param backoffPolicy - Function to generate delay time based on current retry count.\n *\n * @returns The result of the operation.\n * @throws An error if the operation fails after the maximum number of retries.\n *\n * @example\n * const result = await retry(\n * async () => {\n * const response = await fetch('https://example.com')\n * return response.json()\n * },\n * result => result.status === 200\n * )\n */\nexport const retry = async <T>({\n operation,\n isSuccess,\n maxRetries = DEFAULT_MAX_RETRIES,\n backoffPolicy = RetryBackoffPolicy.exponential(),\n}: RetryParams<T>): Promise<T> => {\n let backoffPeriodMillis = 0;\n let retries = 0;\n let lastError: unknown;\n\n while (retries < maxRetries) {\n if (retries > 0) {\n await delay(backoffPeriodMillis);\n }\n\n try {\n const result = await operation(retries);\n\n if (isSuccess(result)) {\n return result;\n }\n } catch (err) {\n // when the operation throws an error, we still retry\n lastError = err;\n }\n\n backoffPeriodMillis = backoffPolicy(retries);\n retries++;\n }\n\n const errorMessage = lastError ? `Max retry exceeded. ${lastError}` : 'Max retry exceeded.';\n\n throw new Error(errorMessage);\n};\n\ntype RetryBackoffPolicyInterface = (retryIndex: number) => number;\n\nexport class RetryBackoffPolicy {\n static exponential(): RetryBackoffPolicyInterface {\n return (retryIndex: number): number => {\n return Math.pow(2, retryIndex) * 1000;\n };\n }\n\n static constant(secondsToDelay: number): RetryBackoffPolicyInterface {\n return (_: number): number => {\n return secondsToDelay * 1000;\n };\n }\n\n static constantMs(msToDelay: number): RetryBackoffPolicyInterface {\n return (_: number): number => {\n return msToDelay;\n };\n }\n\n /**\n * linearThenExponential backoff:\n * - First `linearCount` retries: linear increase by `linearStepMs`\n * - After that: increment grows exponentially based on `linearStepMs`\n * Example (linearCount=4, linearStepMs=1000):\n * 1s, 2s, 3s, 4s, 6s, 10s, 18s, 34s...\n */\n static linearThenExponential(linearCount: number, linearStepMs: number): RetryBackoffPolicyInterface {\n return (retryIndex: number): number => {\n if (retryIndex < linearCount) {\n // Linear phase: (i+1) * step\n return (retryIndex + 1) * linearStepMs;\n }\n // Exponential-increment phase (closed form):\n // n = number of exponential increments applied\n // base = linearCount * step\n // increment sum = 2*step * (2^n - 1)\n const n = retryIndex - linearCount + 1;\n const base = linearCount * linearStepMs;\n const incSum = 2 * linearStepMs * (Math.pow(2, n) - 1);\n return base + incSum;\n };\n }\n}\n\nfunction delay(ms: number) {\n return new Promise((r) => setTimeout(r, ms));\n}\n","import { RetryBackoffPolicy, retry } from './retry';\n\ntype Error = {\n status: {\n error_code: number;\n error_message: string;\n };\n};\n\nexport const coingeckoRetry = <T>(\n operation: (useCoingeckoProxy: boolean) => Promise<T | Error>,\n): Promise<T | undefined> => {\n return retry({\n operation: (retryIndex: number) => operation(retryIndex > 0),\n maxRetries: 2,\n backoffPolicy: RetryBackoffPolicy.constant(1),\n isSuccess: (response: T | Error) => {\n const errorStatus = (response as Error)?.status;\n return errorStatus?.error_code !== 429;\n },\n }) as Promise<T | undefined>;\n};\n","export function charsum(s: string): number {\n let i,\n sum = 0;\n for (i = 0; i < s.length; i++) {\n sum += s.charCodeAt(i) * (i + 1);\n }\n return sum;\n}\n","import { charsum } from './charsum';\n\n// from https://stackoverflow.com/a/25105589\nexport function arrayHash(array: string[]): string {\n let i,\n sum = 0;\n for (i = 0; i < array.length; i++) {\n const cs = charsum(array[i] ?? '');\n sum = sum + 65027 / cs;\n }\n return ('' + sum).slice(0, 16);\n}\n","import { RawSimplePriceResponseSchema } from '@avalabs/vm-module-types';\nimport { fetchAndVerify } from '../../utils/fetch-and-verify';\n\nexport class CoingeckoProxyClient {\n constructor(private proxyApiUrl: string) {}\n\n simplePrice(params: {\n ids: string[];\n vs_currencies: string[];\n include_market_cap?: boolean;\n include_24hr_vol?: boolean;\n include_24hr_change?: boolean;\n include_last_updated_at?: boolean;\n }) {\n // casting params as any since typing does not allow boolean and other non-string values\n // even though NodeJS does not have this restriction itself: https://nodejs.org/api/url.html#new-urlsearchparamsobj\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const queryParams = new URLSearchParams(params as any);\n return fetchAndVerify(\n [\n `${this.proxyApiUrl}/proxy/coingecko/simple/price?${queryParams}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n RawSimplePriceResponseSchema,\n );\n }\n\n simplePriceByContractAddresses(params: {\n id: string;\n contract_addresses: string[];\n vs_currencies?: string[];\n include_market_cap?: boolean;\n include_24hr_vol?: boolean;\n include_24hr_change?: boolean;\n }) {\n const { id, ...rawQueryParams } = params;\n\n // casting params as any since typing does not allow boolean and other non-string values\n // even though NodeJS does not have this restriction itself: https://nodejs.org/api/url.html#new-urlsearchparamsobj\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const queryParams = new URLSearchParams(rawQueryParams as any);\n\n return fetchAndVerify(\n [\n `${this.proxyApiUrl}/proxy/coingecko/simple/token_price/${id}?${queryParams}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n RawSimplePriceResponseSchema,\n );\n }\n}\n","import z from 'zod';\nimport type { ZodSchema } from 'zod';\n\nexport async function fetchAndVerify<T extends ZodSchema>(\n fetchOptions: Parameters<typeof fetch>,\n schema: T,\n): Promise<z.infer<T>> {\n const response = await fetch(...fetchOptions);\n\n if (!response.ok) {\n throw new Error(`Request failed with status ${response.status}`);\n }\n\n const responseJson = await response.json();\n return schema.parse(responseJson);\n}\n","import { fetchAndVerify } from '../../utils/fetch-and-verify';\nimport { z } from 'zod';\n\nconst WatchlistTokenResponseSchema = z.array(\n z.object({\n // the object has more properties than the ones listed here, but we only need these at the moment\n internalId: z.string(),\n id: z.string(),\n symbol: z.string(),\n name: z.string(),\n image: z.string().optional().nullable(),\n current_price: z.number().optional().nullable(),\n price_change_percentage_24h: z.number().optional().nullable(),\n market_cap: z.number().optional().nullable(),\n total_volume: z.number().optional().nullable(),\n platforms: z.record(z.string(), z.string()),\n }),\n);\n\nexport class WatchlistProxyClient {\n constructor(private proxyApiUrl: string) {}\n\n watchlistToken(params: { tokens: string; currency: string }) {\n // casting params as any since typing does not allow boolean and other non-string values\n // even though NodeJS does not have this restriction itself: https://nodejs.org/api/url.html#new-urlsearchparamsobj\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const queryParams = new URLSearchParams(params as any);\n return fetchAndVerify(\n [\n `${this.proxyApiUrl}/watchlist/tokens?${queryParams}`,\n {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n WatchlistTokenResponseSchema,\n );\n }\n}\n","import z, { number, object, record, string } from 'zod';\nimport { fetchAndVerify } from '../../utils/fetch-and-verify';\n\nconst CURRENCY_EXCHANGE_RATES_URL =\n 'https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/usd.min.json';\n\nconst CURRENCY_EXCHANGE_RATES_FALLBACK_URL = 'https://latest.currency-api.pages.dev/v1/currencies/usd.min.json';\n\nconst ExchangeRateSchema = object({\n date: string(),\n usd: record(number()),\n});\n\ntype ExchangeRate = z.infer<typeof ExchangeRateSchema>;\n\nexport const getExchangeRates = async (): Promise<ExchangeRate> => {\n try {\n return await fetchAndVerify([CURRENCY_EXCHANGE_RATES_URL], ExchangeRateSchema);\n } catch {\n return await fetchAndVerify([CURRENCY_EXCHANGE_RATES_FALLBACK_URL], ExchangeRateSchema);\n }\n};\n","import {\n type AddressItem,\n type CurrencyItem,\n type NodeIDItem,\n type TextItem,\n type DataItem,\n type DateItem,\n type LinkItemValue,\n DetailItemType,\n type LinkItem,\n type FundsRecipientItem,\n type AddressListItem,\n type NetworkItemValue,\n type NetworkItem,\n} from '@avalabs/vm-module-types';\n\nexport const fundsRecipientItem = (\n address: string,\n amount: bigint,\n maxDecimals: number,\n symbol: string,\n): FundsRecipientItem => ({\n type: DetailItemType.FUNDS_RECIPIENT,\n label: address,\n amount,\n maxDecimals,\n symbol,\n});\n\nexport const currencyItem = (label: string, value: bigint, maxDecimals: number, symbol: string): CurrencyItem => ({\n label,\n type: DetailItemType.CURRENCY,\n value,\n maxDecimals,\n symbol,\n});\n\nexport const textItem = (\n label: string,\n value: string,\n alignment: 'horizontal' | 'vertical' = 'horizontal',\n): TextItem => ({\n label,\n alignment,\n type: DetailItemType.TEXT,\n value,\n});\n\nexport const linkItem = (label: string, value: LinkItemValue): LinkItem => ({\n label,\n value,\n type: DetailItemType.LINK,\n});\n\nexport const addressItem = (label: string, value: string): AddressItem => ({\n label,\n type: DetailItemType.ADDRESS,\n value,\n});\n\nexport const addressListItem = (label: string, value: string[]): AddressListItem => ({\n label,\n type: DetailItemType.ADDRESS_LIST,\n value,\n});\n\nexport const nodeIDItem = (label: string, value: string): NodeIDItem => ({\n label,\n type: DetailItemType.NODE_ID,\n value,\n});\n\nexport const dataItem = (label: string, value: string): DataItem => ({\n label,\n type: DetailItemType.DATA,\n value,\n});\n\nexport const dateItem = (label: string, value: string): DateItem => ({\n label,\n type: DetailItemType.DATE,\n value,\n});\n\nexport const networkItem = (label: string, value: NetworkItemValue): NetworkItem => ({\n label,\n type: DetailItemType.NETWORK,\n value,\n});\n","import { AppName, type AppInfo } from '@avalabs/vm-module-types';\n\nexport const getCoreHeaders = ({ name, version }: AppInfo): Record<string, string> | undefined => {\n switch (name) {\n case AppName.CORE_MOBILE_IOS:\n case AppName.CORE_MOBILE_ANDROID:\n case AppName.CORE_WEB:\n case AppName.CORE_EXTENSION:\n case AppName.EXPLORER:\n return {\n 'x-application-name': name,\n 'x-application-version': version,\n };\n case AppName.OTHER:\n return undefined;\n }\n};\n","export const GLACIER_API_KEY = process.env.GLACIER_API_KEY;\n","import { GLACIER_API_KEY } from '../consts';\n\n// this key is only needed in development to bypass rate limit\n// it should never be used in production\nexport const getGlacierApiKey = (): string | undefined => {\n return GLACIER_API_KEY;\n};\n","import { FetchHttpRequest, type OpenAPIConfig, type ApiRequestOptions, CancelablePromise } from '@avalabs/glacier-sdk';\nimport { getGlacierApiKey } from './get-glacier-api-key';\n\nconst GLOBAL_QUERY_PARAMS: Record<string, string | undefined> = {\n rltoken: getGlacierApiKey(),\n};\n\n/**\n * Custom HTTP request handler that automatically appends the Glacier API key (if present)\n * to bypass rate limits in development environments.\n */\nexport class GlacierFetchHttpRequest extends FetchHttpRequest {\n constructor(config: OpenAPIConfig) {\n super(config);\n }\n\n public override request<T>(options: ApiRequestOptions): CancelablePromise<T> {\n // Merge global query parameters with request-specific ones\n const mergedQuery = {\n ...GLOBAL_QUERY_PARAMS,\n ...(options.query || {}), // Request-specific params (override globals if same key)\n };\n\n // Create modified options with merged query\n const modifiedOptions: ApiRequestOptions = {\n ...options,\n query: Object.keys(mergedQuery).length > 0 ? mergedQuery : undefined,\n };\n\n // Call the base class's request method\n return super.request<T>(modifiedOptions);\n }\n}\n","{\n \"name\": \"SVM\",\n \"description\": \"\",\n \"version\": \"0.0.1\",\n \"sources\": {\n \"module\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/index.js\",\n \"packageName\": \"@avalabs/svm-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n },\n \"provider\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/provider/index.js\",\n \"packageName\": \"@avalabs/svm-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\n \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\"\n ],\n \"namespaces\": [\"solana\"]\n },\n \"cointype\": \"501\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"solana_signTransaction\", \"solana_signAndSendTransaction\", \"solana_signMessage\"],\n \"nonRestrictedMethods\": []\n }\n },\n \"manifestVersion\": \"0.1\"\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n proxyApiUrl: 'https://proxy-api-dev.avax.network',\n};\n\nexport const getEnv = (environment: Environment): Env => {\n switch (environment) {\n case Environment.PRODUCTION:\n return prodEnv;\n case Environment.DEV:\n return devEnv;\n }\n};\n","import type { ApprovalController, DeriveAddressParams, DeriveAddressResponse } from '@avalabs/vm-module-types';\nimport { NetworkVMType } from '@avalabs/vm-module-types';\nimport { base58, hex } from '@scure/base';\n\nimport { hasDerivationDetails } from '@internal/utils/src/utils/address-derivation';\nimport { buildDerivationPath } from '../build-derivation-path/build-derivation-path';\n\nexport const deriveAddress = async (\n params: DeriveAddressParams & { approvalController: ApprovalController },\n): Promise<DeriveAddressResponse> => {\n const { approvalController, secretId } = params;\n\n // When dealing with single-account private keys, we don't need the derivation path any more.\n const derivationPath = hasDerivationDetails(params) ? buildDerivationPath(params).SVM : undefined;\n const publicKeyHex = await approvalController.requestPublicKey({\n curve: 'ed25519',\n secretId,\n derivationPath,\n });\n\n return {\n [NetworkVMType.SVM]: base58.encode(hex.decode(publicKeyHex)),\n };\n};\n","import type { DeriveAddressParams, DetailedDeriveAddressParams } from '@avalabs/vm-module-types';\n\nexport const hasDerivationDetails = (params: DeriveAddressParams): params is DetailedDeriveAddressParams =>\n 'derivationPathType' in params &&\n 'accountIndex' in params &&\n typeof params.accountIndex === 'number' &&\n typeof params.derivationPathType === 'string';\n","import {\n NetworkVMType,\n type BuildDerivationPathParams,\n type BuildDerivationPathResponse,\n} from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\n/**\n * We're deriving the BTC address from the same public key as the Ethereum address,\n * so we can determine the target address when using the Avalanche Bridge.\n */\nexport const buildDerivationPath = ({\n accountIndex,\n}: BuildDerivationPathParams): Pick<BuildDerivationPathResponse, NetworkVMType.SVM> => {\n if (accountIndex < 0) {\n throw rpcErrors.invalidParams('Account index must be a non-negative integer');\n }\n\n return {\n [NetworkVMType.SVM]: `m/44'/501'/${accountIndex}'/0'`,\n };\n};\n","import { type NetworkFeeParam, type NetworkFees } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { SOL_DECIMALS } from '@src/constants';\n\nconst LamportsMultiplier = 1e6;\nexport const DEFAULT_PRIORITY_FEE = {\n high: 150 * LamportsMultiplier,\n medium: 75 * LamportsMultiplier,\n low: 2 * LamportsMultiplier,\n} as const;\n\ntype ValidRecentFees = [number, number, ...number[]];\n\nconst ensureEnoughData = (fees: number[]): ValidRecentFees => {\n const normalizedFees =\n fees.length === 0\n ? [DEFAULT_PRIORITY_FEE.low, DEFAULT_PRIORITY_FEE.low]\n : fees.length === 1\n ? [fees[0]!, DEFAULT_PRIORITY_FEE.low]\n : fees;\n\n return normalizedFees.slice().sort((a, b) => a - b) as ValidRecentFees;\n};\n\n/**\n * The RPC call (getRecentPrioritizationFees) returns the *lowest* priority fees (per compute unit)\n * that resulted in at least one transaction being succesfully included in the block.\n *\n * This means the request usually returns all zeroes - I've only once seen a different value,\n * for a single block out of 150 returned, and it was a 1000 MicroLamports.\n *\n * However, Phantom (the most popular Solana wallet) seems to always add at least a little bit\n * of priority fee.\n *\n * The lowest I've seen in my testing was 0.19 Lamport per compute unit, but this was an outlier.\n * I'm usually paying below 10 Lamports/cu, and sometimes as high as 150 or 300/cu -- all while\n * the RPC call returns zeroes, so it's not super reliable for determining the actual fees being paid :)\n *\n * The implementation here is by no means perfect. The way it I expect it to work is the following:\n * - with low/regular network traffic, users will be suggested to pay the default fees hardcoded below\n * (if we decide to show them at all -- Phantom does not show a widget at all)\n * - only when network congestion is super high, the RPC call will return non-zero values, and only then\n * we will suggest paying higher priority fees.\n */\nexport async function getNetworkFee(network: NetworkFeeParam, proxyApiUrl: string): Promise<NetworkFees> {\n const provider = getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl });\n\n const getFees = await provider.getRecentPrioritizationFees();\n const feesRaw = await getFees.send();\n\n const useDefaultFees = feesRaw.length === 0 || feesRaw.every((block) => block.prioritizationFee === 0n);\n\n if (useDefaultFees) {\n return {\n high: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.high),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.high),\n },\n medium: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.medium),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.medium),\n },\n low: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.low),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.low),\n },\n baseFee: BigInt(DEFAULT_PRIORITY_FEE.low),\n displayDecimals: SOL_DECIMALS,\n isFixedFee: false,\n };\n }\n\n const sortedFees = ensureEnoughData(feesRaw.map((block) => Number(block.prioritizationFee)));\n // We know the array is not empty and sorted, so we can safely access the first and last elements\n const minFeeInRecentBlocks = sortedFees.at(0)!;\n const maxFeeInRecentBlocks = sortedFees.at(-1)!;\n const midIndex = Math.floor(sortedFees.length / 2);\n const medianFee =\n sortedFees.length % 2 === 1\n ? (sortedFees[midIndex] as number)\n : (sortedFees[midIndex - 1]! + sortedFees[midIndex]!) / 2; // Even length: return average of middle elements\n\n // Prevent the fees from going below the default values\n // If the RPC call returned non-zero values, the network congestion is likely to be very high, so we add 5%.\n // We also prevent returning fees lower than the default, hardcoded values, as the RPC call is not very reliable.\n const presetHigh = BigInt(Math.ceil(maxFeeInRecentBlocks * 1.05));\n const presetMedium = BigInt(Math.ceil(medianFee * 1.05));\n const presetLow = BigInt(Math.ceil(minFeeInRecentBlocks * 1.05));\n\n // TODO: The shape of response here needs a general refactoring, it's not very generic.\n return {\n high: {\n maxFeePerGas: presetHigh,\n maxPriorityFeePerGas: presetHigh,\n },\n medium: {\n maxFeePerGas: presetMedium,\n maxPriorityFeePerGas: presetMedium,\n },\n low: {\n maxFeePerGas: presetLow,\n maxPriorityFeePerGas: presetLow,\n },\n baseFee: presetLow,\n displayDecimals: SOL_DECIMALS,\n isFixedFee: false,\n };\n}\n","import { getSolanaProvider, type SolanaProvider } from '@avalabs/core-wallets-sdk';\n\nimport { RPC_URL_DEVNET, RPC_URL_PROXY_API_ENDPOINT } from '../constants';\n\nexport const getProvider = ({\n isTestnet,\n proxyApiUrl,\n}: {\n isTestnet: boolean;\n proxyApiUrl: string;\n}): SolanaProvider => {\n return getSolanaProvider({\n isTestnet,\n rpcUrl: isTestnet ? RPC_URL_DEVNET : proxyApiUrl + RPC_URL_PROXY_API_ENDPOINT,\n });\n};\n","export const SOL_DECIMALS = 9;\nexport const SOLANA_COIN_ID = 501;\n\nexport const SOLANA_MAINNET_CAIP2_ID = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET_CAIP2_ID = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET_CAIP2_ID = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\nexport const RPC_URL_PROXY_API_ENDPOINT = '/proxy/nownodes/sol';\nexport const RPC_URL_DEVNET = 'https://api.devnet.solana.com';\nexport const RPC_URL_TESTNET = 'https://api.testnet.solana.com';\n\nexport const BLOCKAID_API_KEY = 'DUMMY_API_KEY'; // since we're using our own proxy and api key is handled there, we can use a dummy key here\n","import type { SPLToken } from '@avalabs/vm-module-types';\nimport { fetchAndVerify } from '@internal/utils/src/utils/fetch-and-verify';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { SPL_TOKENS_SCHEMA } from './spl-token-schema';\n\nexport async function getTokens({\n caip2Id,\n proxyApiUrl,\n}: {\n caip2Id: string;\n proxyApiUrl: string;\n}): Promise<SPLToken[]> {\n try {\n const tokens = await fetchAndVerify([`${proxyApiUrl}/solana-tokens?caip2Id=${caip2Id}`], SPL_TOKENS_SCHEMA);\n\n return tokens.map((token) => ({ ...token, type: token.contractType }));\n } catch (error) {\n console.error('getTokens() failed for', caip2Id, error);\n throw rpcErrors.internal(`Failed to fetch tokens for caip2Id \"${caip2Id}\"`);\n }\n}\n","import { TokenType } from '@avalabs/vm-module-types';\nimport { z } from 'zod';\n\nexport const SPL_TOKEN_SCHEMA = z.object({\n address: z.string(),\n name: z.string(),\n symbol: z.string(),\n contractType: z.literal(TokenType.SPL),\n caip2Id: z.string().startsWith('solana:'),\n decimals: z.number(),\n chainId: z.number().optional(),\n logoUri: z.string().optional(),\n color: z.string().optional(),\n});\n\nexport const SPL_TOKENS_SCHEMA = z.array(SPL_TOKEN_SCHEMA);\n","import {\n type GetBalancesParams,\n type TokenWithBalanceSVM,\n type TokenWithBalanceSPL,\n TokenType,\n type SimplePriceResponse,\n type Error,\n} from '@avalabs/vm-module-types';\nimport { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { VsCurrencyType } from '@avalabs/core-coingecko-sdk';\n\nimport type { TokenService } from '@internal/utils';\n\nimport { SOL_DECIMALS } from '@src/constants';\nimport { MoralisService } from '@src/utils/moralis-service';\nimport { getNetworkName } from '@src/utils/get-network-name';\n\ntype GetSolanaBalancesResponse = Record<\n string,\n Record<string, TokenWithBalanceSVM | TokenWithBalanceSPL | Error> | Error\n>;\n\nexport const getBalances = async ({\n addresses,\n proxyApiUrl,\n currency,\n network,\n tokenService,\n}: GetBalancesParams & {\n proxyApiUrl: string;\n tokenService: TokenService;\n}): Promise<GetSolanaBalancesResponse> => {\n const moralisService = new MoralisService({ proxyApiUrl });\n const coingeckoAssetId = network.pricingProviders?.coingecko.nativeTokenId ?? '';\n const coingeckoPlatformId = network.pricingProviders?.coingecko.assetPlatformId ?? '';\n const lowercaseCurrency = currency.toLowerCase();\n const solanaNetwork = getNetworkName(network);\n\n const portfolioResults = await Promise.all(\n addresses.map((address) => moralisService.getPortfolio({ address, network: solanaNetwork })),\n );\n\n const mints = new Set(\n portfolioResults.flatMap((result) => {\n if ('portfolio' in result) {\n return result.portfolio.tokens.map(({ mint }) => mint);\n }\n\n return [];\n }),\n );\n\n const tokenPrices = await (coingeckoPlatformId\n ? tokenService.getPricesByAddresses(Array.from(mints), coingeckoPlatformId, lowercaseCurrency as VsCurrencyType)\n : Promise.resolve(undefined));\n\n const nativeMarketData = await tokenService.getWatchlistDataForToken({\n tokenDetails: {\n symbol: network.networkToken.symbol,\n isNative: true,\n caip2Id: network.caipId ?? '',\n },\n currency: lowercaseCurrency as VsCurrencyType,\n });\n\n return portfolioResults.reduce((portfolioAcc, result) => {\n if ('error' in result) {\n return {\n ...portfolioAcc,\n [result.address]: {\n error: result.error,\n },\n };\n }\n\n const nativeBalanceUnit = new TokenUnit(result.portfolio.nativeBalance.lamports, SOL_DECIMALS, 'SOL');\n\n const nativeBalanceInCurrency =\n nativeMarketData.priceInCurrency !== undefined\n ? nativeBalanceUnit.mul(nativeMarketData.priceInCurrency)\n : undefined;\n\n const solanaBalance: TokenWithBalanceSVM = {\n type: TokenType.NATIVE,\n name: network.networkToken.name,\n symbol: network.networkToken.symbol,\n decimals: network.networkToken.decimals,\n balance: nativeBalanceUnit.toSubUnit(),\n balanceDisplayValue: nativeBalanceUnit.toString(),\n balanceInCurrency: nativeBalanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: nativeBalanceInCurrency?.toDisplay({ fixedDp: 2 }),\n logoUri: network.networkToken.logoUri ?? '',\n coingeckoId: coingeckoAssetId,\n ...nativeMarketData,\n };\n\n const tokenBalances = result.portfolio.tokens.reduce(\n (tokensAcc, { amountRaw, symbol, decimals, mint, name, logo }) => {\n const balanceUnit = new TokenUnit(amountRaw, decimals, symbol);\n const marketData = getMarketData(mint, lowercaseCurrency, tokenPrices);\n const balanceInCurrency =\n marketData.priceInCurrency !== undefined ? balanceUnit.mul(marketData.priceInCurrency) : undefined;\n\n const token: TokenWithBalanceSPL = {\n type: TokenType.SPL,\n address: mint,\n name,\n symbol,\n decimals,\n balance: balanceUnit.toSubUnit(),\n balanceDisplayValue: balanceUnit.toString(),\n balanceInCurrency: balanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: balanceInCurrency?.toDisplay({ fixedDp: 2 }),\n logoUri: logo ?? undefined,\n reputation: null,\n ...marketData,\n };\n\n return {\n ...tokensAcc,\n [mint]: token,\n };\n },\n {} as Record<string, TokenWithBalanceSPL>,\n );\n\n return {\n ...portfolioAcc,\n [result.address]: {\n [network.networkToken.symbol]: solanaBalance,\n ...tokenBalances,\n },\n };\n }, {} as GetSolanaBalancesResponse);\n};\n\nconst getMarketData = (coinIdOrAddress: string, currency: string, prices?: SimplePriceResponse) => ({\n priceInCurrency: prices?.[coinIdOrAddress ?? '']?.[currency]?.price ?? undefined,\n marketCap: prices?.[coinIdOrAddress ?? '']?.[currency]?.marketCap ?? undefined,\n vol24: prices?.[coinIdOrAddress ?? '']?.[currency]?.vol24 ?? undefined,\n change24: prices?.[coinIdOrAddress ?? '']?.[currency]?.change24 ?? undefined,\n});\n","import { z } from 'zod';\n\nexport const PORTFOLIO_SCHEMA = z.object({\n nativeBalance: z.object({\n lamports: z.string(),\n solana: z.string(),\n }),\n nfts: z.array(\n z.object({\n associatedTokenAddress: z.string(),\n mint: z.string(),\n name: z.string(),\n symbol: z.string(),\n }),\n ),\n tokens: z.array(\n z.object({\n associatedTokenAddress: z.string(),\n mint: z.string(),\n amountRaw: z.string(),\n amount: z.string(),\n decimals: z.number(),\n name: z.string(),\n symbol: z.string(),\n logo: z.string().optional().nullable(),\n }),\n ),\n});\n\nexport type PortfolioResponse = z.infer<typeof PORTFOLIO_SCHEMA>;\n","import { fetchAndVerify } from '@internal/utils/src/utils/fetch-and-verify';\n\nimport type { SolanaNetworkName } from '@src/types';\n\nimport { PORTFOLIO_SCHEMA, type PortfolioResponse } from './moralis-schemas';\n\nexport class MoralisService {\n #baseUrl: string;\n\n constructor({ proxyApiUrl }: { proxyApiUrl: string }) {\n this.#baseUrl = `${proxyApiUrl}/proxy/moralis`;\n }\n\n async getPortfolio({\n address,\n network,\n }: {\n network: SolanaNetworkName;\n address: string;\n }): Promise<{ address: string; portfolio: PortfolioResponse } | { address: string; error: string }> {\n try {\n const url = this.#buildUrl(`/account/${network}/${address}/portfolio`);\n const portfolio = await fetchAndVerify([url], PORTFOLIO_SCHEMA);\n\n return {\n address,\n portfolio,\n };\n } catch (error) {\n console.error('getPortfolio() failed:', error);\n\n const message = error instanceof Error ? error.message : 'unknown error';\n\n return {\n address,\n error: `getPortfolio() failed: ${message}`,\n };\n }\n }\n\n #buildUrl(path: string) {\n return `${this.#baseUrl}${path}`;\n }\n}\n","import type { Network } from '@avalabs/vm-module-types';\n\nimport { SOLANA_DEVNET_CAIP2_ID, SOLANA_MAINNET_CAIP2_ID, SOLANA_TESTNET_CAIP2_ID } from '../constants';\n\nexport const getNetworkName = (network: Network) => {\n switch (network.caipId) {\n case SOLANA_MAINNET_CAIP2_ID:\n return 'mainnet';\n\n case SOLANA_DEVNET_CAIP2_ID:\n return 'devnet';\n\n case SOLANA_TESTNET_CAIP2_ID:\n return 'testnet';\n\n default:\n throw new Error('Unrecognized CAIP-2 id: ' + network.caipId);\n }\n};\n","import { TransactionType, type Network, type TransactionHistoryResponse, type TxToken } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\nimport { extractTokenTranfers, simplifyTokenBalance } from './extract-transfer';\nimport { getWrappedTransactions } from './get-wrapped-transactions';\nimport { getExplorerLink } from './get-explorer-link';\n\ntype SvmGetTransactionHistory = {\n network: Network;\n address: string;\n proxyApiUrl: string;\n};\n\nexport async function getTransactionHistory({\n network,\n address,\n proxyApiUrl,\n}: SvmGetTransactionHistory): Promise<TransactionHistoryResponse> {\n if (!network.caipId) {\n return Promise.reject({\n error: rpcErrors.invalidParams(`Network must have a CAIP-2 id`),\n });\n }\n\n const rawTransactions = await getWrappedTransactions({ network, address, proxyApiUrl });\n\n const transactions = rawTransactions\n .map(({ txHash, tx }) => {\n if (!tx.meta) {\n return null;\n }\n\n const {\n meta,\n transaction: { message },\n } = tx;\n\n // Typings are wrong here, .toString() fixes it without unnecessary casting\n const addresses = message.accountKeys.map((acc) => acc.toString());\n let accountIndex = addresses.indexOf(address);\n let isOurAddressInTransaction = accountIndex !== -1;\n\n // If not in accountKeys, check if we're an owner in token balances (for ATA transactions)\n if (!isOurAddressInTransaction && meta.preTokenBalances) {\n const isOwnerInTokenBalances =\n meta.preTokenBalances.some((balance) => balance.owner === address) ||\n (meta.postTokenBalances ?? []).some((balance) => balance.owner === address);\n if (isOwnerInTokenBalances) {\n isOurAddressInTransaction = true;\n // Set accountIndex to -1 to indicate we're not directly in accountKeys but are involved via token balances\n accountIndex = -1;\n }\n }\n\n // accountKeys property is sorted in Solana transactions. The signing keys\n // are always the first, and the header.numRequiredSignatures tells us how many\n // of the first keys are signers. If the lookup address is a signer, it has to be\n // one of the first N keys. For ATA transactions (accountIndex = -1), we're not a direct signer.\n const isSigner = accountIndex !== -1 && accountIndex < message.header.numRequiredSignatures;\n\n const transfers = extractTokenTranfers(\n addresses,\n accountIndex,\n {\n paidFee: isSigner ? Number(meta.fee) : 0,\n preBalances: meta.preBalances.map(Number),\n postBalances: meta.postBalances.map(Number),\n preTokenBalances: (meta.preTokenBalances ?? []).map(simplifyTokenBalance),\n postTokenBalances: (meta.postTokenBalances ?? []).map(simplifyTokenBalance),\n },\n network,\n );\n\n const txType = inferTxType(transfers, address);\n\n return {\n hash: txHash,\n // We should probably be smarter about the tx type, but this should be enough for MVP\n txType,\n gasUsed: String(tx.meta.computeUnitsConsumed ?? '0'),\n tokens: transfers,\n\n // Get to/from addresses from the token transfers if possible.\n // If not possible:\n // - default \"from\" to the signing address\n // - default \"to\" to our address if we're not the signer and leave empty if we don't know.\n from: transfers[0]?.from?.address ?? (addresses[0] as string),\n to: transfers[0]?.to?.address ?? (isSigner ? '' : address),\n isOutgoing: isSigner,\n isIncoming: !isSigner,\n isSender: isSigner,\n timestamp: Number(tx.blockTime) * 1000,\n isContractCall: false,\n gasPrice: String(Number(tx.meta.fee) / Number(tx.meta.computeUnitsConsumed)),\n chainId: String(network.chainId),\n explorerLink: getExplorerLink(txHash, network.explorerUrl),\n };\n })\n .filter(<T>(tx: T): tx is NonNullable<T> => tx !== null);\n\n return {\n transactions,\n };\n}\n\nconst inferTxType = (transfers: TxToken[], address: string) => {\n // No transfers = unknown\n if (transfers.length === 0) {\n return TransactionType.UNKNOWN;\n }\n\n // Check if we're the sender or receiver for each token transfer\n const ourTransfers = transfers.filter((t) => t.from?.address === address || t.to?.address === address);\n\n // If we have no transfers involving our address, it's unknown\n if (ourTransfers.length === 0) {\n return TransactionType.UNKNOWN;\n }\n\n // Check if we have both sending and receiving transfers\n const hasSending = ourTransfers.some((t) => t.from?.address === address);\n const hasReceiving = ourTransfers.some((t) => t.to?.address === address);\n\n // If we're both sending and receiving, it's a swap\n if (hasSending && hasReceiving) {\n return TransactionType.SWAP;\n }\n\n // If we're only sending\n if (hasSending) {\n return TransactionType.SEND;\n }\n\n // If we're only receiving\n if (hasReceiving) {\n return TransactionType.RECEIVE;\n }\n\n return TransactionType.UNKNOWN;\n};\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport { TokenType, type Network, type SPLToken, type TxToken } from '@avalabs/vm-module-types';\nimport type { TokenBalance } from '@solana/kit';\n\nexport const simplifyTokenBalance = (balance: TokenBalance): SimpleTokenBalance => ({\n mint: balance.mint as string,\n owner: balance.owner as string,\n amount: BigInt(balance.uiTokenAmount.amount),\n decimals: balance.uiTokenAmount.decimals,\n});\n\nexport const extractTokenTranfers: ExtractTransferFn<'SPL'> = (addresses, accountIndex, meta, network): TxToken[] => {\n // For ATA transactions (accountIndex = -1), find our address from token balances\n const ourAddress =\n accountIndex !== -1\n ? addresses[accountIndex]\n : meta.preTokenBalances.find((balance) => !addresses.includes(balance.owner))?.owner ||\n meta.postTokenBalances.find((balance) => !addresses.includes(balance.owner))?.owner;\n\n // Create a map of initial balances\n const preBalances: Record<string, bigint> = meta.preTokenBalances.reduce(\n (acc, { owner, mint, amount }) => ({\n ...acc,\n [`${owner}-${mint}`]: amount,\n }),\n {},\n );\n\n // Compare with post balances to determine transfers\n const transfers = meta.postTokenBalances.reduce((acc, { owner, mint, amount, decimals }) => {\n const key = `${owner}-${mint}`;\n const preAmount = preBalances[key] ?? 0n;\n const netChange = amount - preAmount;\n\n // Skip if no balance change\n if (netChange === 0n) {\n return acc;\n }\n\n // Determine if this is a receive or send based on balance change\n const isReceive = netChange > 0n && owner === ourAddress;\n const isSend = netChange < 0n && owner === ourAddress;\n\n if (isReceive) {\n // For receives, we need to find who sent it\n\n // For receives, find the sender by looking for addresses that had the token before but not after (or decreased)\n const sender = Object.keys(preBalances).find((k) => {\n const [possibleSender, mintFromPreBalance] = k.split('-');\n\n // Skip if it's not the same mint\n if (mintFromPreBalance !== mint) return false;\n\n // Skip if it's our address\n if (possibleSender === ourAddress) return false;\n\n // Check if this address had a balance before but not after (or decreased)\n const preBalance = preBalances[k]!;\n const postBalance = meta.postTokenBalances.find(\n ({ owner, mint: postMint }) => owner === possibleSender && postMint === mint,\n );\n\n // If no post balance, or balance decreased, this is likely the sender\n const isSender = !postBalance || postBalance.amount < preBalance;\n\n return isSender;\n });\n\n if (!sender) {\n return acc;\n }\n\n const token =\n network.tokens?.filter((t): t is SPLToken => 'contractType' in t).find((t) => t.address === mint) ??\n ({\n contractType: TokenType.SPL,\n decimals,\n address: mint,\n symbol: 'Unknown',\n name: 'Unknown',\n } as SPLToken);\n\n const transfer: TxToken = {\n ...token,\n type: token.contractType,\n from: {\n ...token,\n address: sender.split('-')[0]!,\n },\n to: {\n ...token,\n address: owner,\n },\n amount: new TokenUnit(netChange, decimals, '').toDisplay(),\n };\n\n return [...acc, transfer];\n } else if (isSend) {\n // For sends, we need to find who received it\n\n const recipient = meta.postTokenBalances.find(\n ({ owner: postBalanceOwner, mint: postBalanceMint }) =>\n postBalanceMint === mint &&\n postBalanceOwner !== ourAddress &&\n (preBalances[`${postBalanceOwner}-${mint}`] ?? 0n) <\n (meta.postTokenBalances.find((p) => p.owner === postBalanceOwner && p.mint === mint)?.amount ?? 0n),\n );\n\n if (!recipient) {\n return acc;\n }\n\n const token =\n network.tokens?.filter((t): t is SPLToken => 'contractType' in t).find((t) => t.address === mint) ??\n ({\n contractType: TokenType.SPL,\n decimals,\n address: mint,\n symbol: 'Unknown',\n name: 'Unknown',\n } as SPLToken);\n\n const transfer: TxToken = {\n ...token,\n type: token.contractType,\n from: {\n ...token,\n address: ourAddress!,\n },\n to: {\n ...token,\n address: recipient.owner,\n },\n amount: new TokenUnit(-netChange, decimals, '').toDisplay(), // Make positive for display\n };\n\n return [...acc, transfer];\n }\n\n // Skip if not our transaction\n return acc;\n }, [] as TxToken[]);\n\n const nativeTransfer = extractNativeTransfer(addresses, accountIndex, meta, network, transfers, ourAddress);\n\n if (nativeTransfer) {\n transfers.push(nativeTransfer);\n }\n\n return transfers;\n};\n\nconst extractNativeTransfer = (\n addresses: string[],\n accountIndex: number,\n { paidFee, preBalances, postBalances }: { paidFee: number; preBalances: number[]; postBalances: number[] },\n network: Network,\n splTransfers: TxToken[] = [],\n ourAddress?: string,\n): TxToken | null => {\n // For ATA transactions (accountIndex = -1), check if this might be a SOL → SPL swap\n if (accountIndex === -1) {\n // Only create SOL transfers for ATA transactions if:\n // 1. We have SPL transfers (swap context)\n // 2. We received SPL tokens (indicating we might have spent SOL)\n // 3. There's significant SOL movement in the transaction\n if (splTransfers.length > 0 && ourAddress) {\n const receivedSPL = splTransfers.some((transfer) => transfer.to?.address === ourAddress);\n\n if (receivedSPL) {\n // Find our address in the addresses array to get balance changes\n const ourAccountIndex = addresses.findIndex((addr) => addr === ourAddress);\n\n if (ourAccountIndex !== -1) {\n // We found our address - check if we spent SOL\n const nativeBalancePre = preBalances[ourAccountIndex]!;\n const nativeBalancePost = postBalances[ourAccountIndex]!;\n const rawBalanceChange = nativeBalancePost - nativeBalancePre;\n\n // If we spent SOL (including fees), create a SOL transfer for the swap\n if (rawBalanceChange <= 0) {\n const solSpent = Math.abs(rawBalanceChange) + paidFee;\n\n // Only create transfer if we spent a meaningful amount\n if (solSpent > paidFee) {\n const unit = new TokenUnit(solSpent, network.networkToken.decimals, '');\n\n // Find who received the most SOL (likely the program/pool)\n const balanceDiffs = postBalances.map((b, i) => b - preBalances[i]!);\n const largestSOLRecipient = balanceDiffs.reduce(\n (max, diff, i) => {\n if (i !== ourAccountIndex && diff > max.amount && diff > 0) {\n return { index: i, amount: diff };\n }\n return max;\n },\n { index: 0, amount: 0 },\n );\n\n return {\n amount: unit.toDisplay(),\n from: {\n address: ourAddress,\n },\n to: {\n address: addresses[largestSOLRecipient.index]!,\n },\n name: network.networkToken.name,\n symbol: network.networkToken.symbol,\n type: TokenType.NATIVE,\n };\n }\n }\n }\n }\n }\n\n return null;\n }\n\n const address = addresses[accountIndex]!;\n const nativeBalancePre = preBalances[accountIndex]!;\n const nativeBalancePost = postBalances[accountIndex]!;\n const rawBalanceChange = nativeBalancePost - nativeBalancePre;\n const balanceDiffs = postBalances.map((b, i) => b - preBalances[i]!);\n\n // Detect if we're in a swap context (SPL transfers present)\n const isSwapContext = splTransfers.length > 0;\n\n let nativeTransferAmount = rawBalanceChange !== 0 ? rawBalanceChange + paidFee : 0;\n let isIncoming = nativeTransferAmount > 0;\n let counterpartyIndex = 0;\n\n // Special case: For SOL → SPL swaps, we need to flip the SOL transfer direction\n // This happens when accountIndex=0 creates an incoming SOL transfer, but we actually spent SOL\n let isSOLtoSPLSwap = false;\n if (isSwapContext && accountIndex === 0 && ourAddress) {\n const receivedSPL = splTransfers.some((transfer) => transfer.to?.address === ourAddress);\n const sentSPL = splTransfers.some((transfer) => transfer.from?.address === ourAddress);\n\n // If we received SPL tokens but didn't send any, this is likely a SOL → SPL swap\n // The SOL transfer should be outgoing (we spent SOL to get SPL)\n if (receivedSPL && !sentSPL) {\n isIncoming = false; // Change from incoming to outgoing\n isSOLtoSPLSwap = true; // Flag to prevent override later\n // Find who received the most SOL (likely the program/pool)\n const balanceDiffs = postBalances.map((b, i) => b - preBalances[i]!);\n const largestSOLRecipient = balanceDiffs.reduce(\n (max, diff, i) => {\n if (i !== accountIndex && diff > max.amount && diff > 0) {\n return { index: i, amount: diff };\n }\n return max;\n },\n { index: 0, amount: 0 },\n );\n counterpartyIndex = largestSOLRecipient.index;\n }\n }\n\n if (isSwapContext && rawBalanceChange < 0) {\n // In a swap, if our balance decreased, look for who gained the most SOL\n // This person likely sent us SOL in the swap\n const largestGainer = balanceDiffs.reduce(\n (max, diff, i) => {\n if (i !== accountIndex && diff > max.amount) {\n return { index: i, amount: diff };\n }\n return max;\n },\n { index: 0, amount: 0 },\n );\n\n // If someone gained significant SOL (more than just fees), we likely received SOL from them\n // BUT don't override if we already detected a SOL → SPL swap\n if (largestGainer.amount > paidFee * 2 && !isSOLtoSPLSwap) {\n nativeTransferAmount = largestGainer.amount;\n isIncoming = true;\n counterpartyIndex = largestGainer.index;\n }\n } else if (isSwapContext && rawBalanceChange <= 0) {\n // Handle SOL → SPL swaps where we spent SOL to get SPL tokens\n // Check if we received SPL tokens (indicating a swap, not just a send)\n const receivedSPL = splTransfers.some((transfer) => transfer.to?.address === address);\n\n if (receivedSPL) {\n // We spent SOL to get SPL tokens - this is a swap\n // Show the SOL we spent (including fees for the total cost)\n nativeTransferAmount = Math.abs(rawBalanceChange) + paidFee;\n isIncoming = false;\n\n // Find who received the most SOL (likely the program/pool)\n const largestSOLRecipient = balanceDiffs.reduce(\n (max, diff, i) => {\n if (i !== accountIndex && diff > max.amount && diff > 0) {\n return { index: i, amount: diff };\n }\n return max;\n },\n { index: 0, amount: 0 },\n );\n\n counterpartyIndex = largestSOLRecipient.index;\n }\n }\n\n if (!nativeTransferAmount) {\n return null;\n }\n\n const unit = new TokenUnit(Math.abs(nativeTransferAmount), network.networkToken.decimals, '');\n\n // For non-swap context, use the original logic\n if (!isSwapContext) {\n const largestBeneficiary = balanceDiffs.reduce(\n ({ index, change }, netChange, i) => {\n if (netChange > change) {\n return { index: i, change: netChange };\n }\n return { index, change };\n },\n { index: 0, change: balanceDiffs[0]! },\n );\n counterpartyIndex = isIncoming ? 0 : largestBeneficiary.index;\n }\n\n // For SOL → SPL swaps, use ourAddress instead of addresses[accountIndex]\n // Handle case where counterpartyIndex is out of bounds\n const counterpartyAddress = addresses[counterpartyIndex];\n const fromAddress = isIncoming ? counterpartyAddress || address : ourAddress || address;\n const toAddress = isIncoming ? ourAddress || address : counterpartyAddress || ourAddress || address;\n\n return {\n amount: unit.toDisplay(),\n from: {\n address: fromAddress,\n },\n to: {\n address: toAddress,\n },\n name: network.networkToken.name,\n symbol: network.networkToken.symbol,\n type: TokenType.NATIVE,\n };\n};\n\ntype SimpleTokenBalance = {\n mint: string;\n owner: string;\n amount: bigint;\n decimals: number;\n};\n\ntype TxMeta = {\n paidFee: number;\n // Native SOL balances\n preBalances: number[];\n postBalances: number[];\n // SPL tokens balances\n preTokenBalances: SimpleTokenBalance[];\n postTokenBalances: SimpleTokenBalance[];\n};\n\ntype ExtractTransferFn<Type extends 'native' | 'SPL'> = (\n addresses: string[],\n accountIndex: number,\n meta: TxMeta,\n network: Network,\n) => Type extends 'native' ? TxToken | null : TxToken[];\n","import { address as solAddress, type GetTransactionApi } from '@solana/kit';\nimport type { Network } from '@avalabs/vm-module-types';\n\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { hasPropertyDefined } from '@src/utils/has-property-defined';\nimport { MoralisService } from '@src/utils/moralis-service';\nimport { getNetworkName } from '@src/utils/get-network-name';\n\ntype ParsedTx = ReturnType<GetTransactionApi['getTransaction']>;\ntype WrappedTransaction = { txHash: string; tx: NonNullable<ParsedTx> };\n\nexport const getWrappedTransactions = async ({\n network,\n address,\n proxyApiUrl,\n}: {\n network: Network;\n address: string;\n proxyApiUrl: string;\n}): Promise<WrappedTransaction[]> => {\n const provider = getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl });\n\n // Get main wallet signatures\n const mainSignaturesResponse = await provider.getSignaturesForAddress(solAddress(address), { limit: 25 }).send();\n const mainSignatures = mainSignaturesResponse.map((sig) => sig.signature);\n\n // Get Associated Token Account addresses from portfolio (simpler, no additional RPC calls)\n let allSignatures = mainSignatures;\n try {\n const moralisService = new MoralisService({ proxyApiUrl });\n const networkName = getNetworkName(network);\n const portfolioResult = await moralisService.getPortfolio({ address, network: networkName });\n\n if ('portfolio' in portfolioResult) {\n // Extract ATA addresses from portfolio tokens and NFTs\n const tokenATAs = portfolioResult.portfolio.tokens.map((token) => token.associatedTokenAddress);\n const nftATAs = portfolioResult.portfolio.nfts.map((nft) => nft.associatedTokenAddress);\n const ataAddresses = [...tokenATAs, ...nftATAs];\n\n // Get signatures for all ATA addresses\n const ataSignaturePromises = ataAddresses.map(async (ataAddress) => {\n try {\n const signaturesResponse = await provider\n .getSignaturesForAddress(solAddress(ataAddress), { limit: 25 })\n .send();\n return signaturesResponse.map((sig) => sig.signature);\n } catch (error) {\n console.error('Failed to get signatures for ATA:', ataAddress, error);\n return [];\n }\n });\n\n const ataSignatureResults = await Promise.allSettled(ataSignaturePromises);\n const ataSignatures = ataSignatureResults\n .filter(isFulfilled)\n .map((result) => result.value)\n .flat();\n\n // Combine and deduplicate all signatures\n allSignatures = Array.from(new Set([...mainSignatures, ...ataSignatures]));\n }\n } catch (error) {\n console.error('ATA discovery failed with error:', error);\n }\n\n // Fetch transaction data for all signatures\n const txsRequests = await Promise.allSettled(\n allSignatures.map(async (sig) => ({\n txHash: sig.toString(),\n tx: await provider.getTransaction(sig, { encoding: 'json', maxSupportedTransactionVersion: 0 }).send(),\n })),\n );\n\n return txsRequests\n .filter(isFulfilled)\n .map((tx) => tx.value)\n .filter(hasPropertyDefined('tx'));\n};\n","export const isFulfilled = <T>(result: PromiseSettledResult<T>): result is PromiseFulfilledResult<T> =>\n result.status === 'fulfilled';\n","export function hasPropertyDefined<T, K extends keyof T>(key: K) {\n return (thing: T): thing is T & Record<K, NonNullable<unknown>> => Boolean(thing[key]);\n}\n","export const getExplorerLink = (txHash: string, baseUrl?: string) => {\n const explorerLink = baseUrl ? new URL(baseUrl) : null;\n\n // Keep the query params in-tact: the Solana explorers like SolScan.io or explorer.solana.com\n // switch between clusters based on the `cluster` query param, not the domain.\n if (explorerLink) {\n explorerLink.pathname = `/tx/${txHash}`;\n }\n\n return explorerLink?.toString() ?? '';\n};\n","import { rpcErrors } from '@metamask/rpc-errors';\nimport {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Network,\n type RpcRequest,\n type SigningData,\n type SigningResult,\n} from '@avalabs/vm-module-types';\nimport { type Base64EncodedWireTransaction } from '@solana/kit';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { getNetworkName } from '@src/utils/get-network-name';\nimport { explainTransaction } from '@src/utils/explain/explain-transaction';\nimport { waitForTransactionConfirmation } from '@src/utils/wait-for-transaction-confirmation';\n\nimport { parseRequestParams, type SendOptions } from './schema';\nimport type Blockaid from '@blockaid/client';\n\nexport const signAndSendTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n blockaid,\n}: {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n blockaid: Blockaid;\n}) => {\n const { params } = request;\n const { data, success, error } = parseRequestParams(params);\n\n if (!success) {\n console.error('invalid params', error);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: error } }),\n };\n }\n\n const [{ account, serializedTx, sendOptions }] = data;\n\n const provider = getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { details, isSimulationSuccessful, alert, balanceChange } = await explainTransaction({\n simulationParams: {\n dAppUrl: request.dappInfo.url,\n params: {\n account,\n chain: getNetworkName(network),\n transactionBase64: serializedTx,\n },\n blockaid,\n },\n network,\n provider,\n });\n\n const displayData: DisplayData = {\n title: 'Do you approve this transaction?',\n network: {\n chainId: network.chainId,\n name: network.chainName,\n logoUri: network.logoUri,\n },\n details,\n alert,\n balanceChange,\n networkFeeSelector: false,\n isSimulationSuccessful,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION,\n account,\n data: serializedTx,\n };\n\n const response = await approvalController.requestApproval({ request, displayData, signingData });\n\n if ('error' in response) {\n return {\n error: response.error,\n };\n }\n\n let txHash;\n\n try {\n txHash = await getTxHash(provider, response, sendOptions);\n await approvalController.onTransactionPending({ txHash, request });\n\n waitForTransactionConfirmation({\n provider,\n txHash,\n approvalController,\n request,\n network,\n commitment: sendOptions?.preflightCommitment,\n });\n\n return {\n result: txHash,\n };\n } catch (error) {\n console.error(error);\n // Note: we don't need to call onTransactionReverted here as waitForTransactionConfirmation handles that\n return {\n error: rpcErrors.internal({ message: 'Transaction failed', data: { cause: error } }),\n };\n }\n};\n\nconst getTxHash = async (\n provider: ReturnType<typeof getProvider>,\n response: SigningResult,\n sendOptions?: SendOptions,\n) => {\n if ('txHash' in response) {\n return response.txHash;\n }\n\n const base58TxHash = await provider\n .sendTransaction(response.signedData as Base64EncodedWireTransaction, {\n ...sendOptions,\n encoding: 'base64',\n })\n .send();\n\n return base58TxHash;\n};\n","import {\n AlertType,\n type Alert,\n type BalanceChange,\n type DetailSection,\n type Network,\n type TransactionSimulationResult,\n} from '@avalabs/vm-module-types';\n\nimport type { getProvider } from '../get-provider';\nimport { getAlertForError, transactionAlerts } from '../transaction-alerts';\n\nimport type { ExplainTxParams } from './types';\nimport { parseTransaction } from './parse-transaction';\nimport { processBalanceChange } from './blockaid/process-balance-change';\nimport { scanSolanaTransaction } from './blockaid/scan-solana-transaction';\nimport { addressItem, dataItem } from '@internal/utils';\nimport { addressListItem } from '@internal/utils/src/utils/detail-item';\n\nexport const explainTransaction = async ({\n simulationParams,\n network,\n provider,\n}: {\n simulationParams: ExplainTxParams;\n network: Network;\n provider: ReturnType<typeof getProvider>;\n}): Promise<TransactionSimulationResult & { details: DetailSection[] }> => {\n const { params } = simulationParams;\n const scanResponse = await scanSolanaTransaction(simulationParams);\n const { simulation, validation } = scanResponse?.result ?? {};\n const genericDetails: DetailSection = {\n title: 'Transaction Details',\n items: [dataItem('Raw Data', simulationParams.params.transactionBase64)],\n };\n const details: DetailSection[] = [genericDetails];\n\n let isSimulationSuccessful = false;\n let balanceChange: BalanceChange | undefined;\n let alert: Alert | undefined;\n\n if (!validation || validation.result_type === 'Warning') {\n alert = transactionAlerts[AlertType.WARNING];\n } else if (validation.result_type === 'Malicious') {\n alert = transactionAlerts[AlertType.DANGER];\n } else if (scanResponse?.error_details) {\n alert = getAlertForError(scanResponse.error_details);\n }\n\n if (simulation) {\n const { balanceChange: processedBalanceChange, otherAffectedAddresses } = processBalanceChange(\n params.account,\n simulation,\n network,\n );\n balanceChange = processedBalanceChange;\n if (otherAffectedAddresses.length > 0) {\n // Check if this is a swap (multiple tokens involved)\n const accountAssetsDiff = simulation.account_summary.account_assets_diff;\n const outgoingAssets = accountAssetsDiff?.filter((asset) => asset.out && asset.out.raw_value > 0) ?? [];\n const incomingAssets = accountAssetsDiff?.filter((asset) => asset.in && asset.in.raw_value > 0) ?? [];\n\n // Swaps: multiple assets changing hands (both outgoing and incoming)\n const isSwap = outgoingAssets.length > 0 && incomingAssets.length > 0;\n\n // For swaps, always show \"Interacting with\" regardless of address count\n // For transfers, use the existing logic\n if (isSwap) {\n genericDetails.items.push(addressItem('Account', params.account));\n genericDetails.items.push(addressListItem('Interacting with', otherAffectedAddresses));\n } else {\n // Original logic for transfers\n genericDetails.items.push(\n addressItem(otherAffectedAddresses.length === 1 ? 'From' : 'Account', params.account),\n );\n genericDetails.items.push(\n otherAffectedAddresses.length === 1\n ? addressItem('To', otherAffectedAddresses[0]!)\n : addressListItem('Interacting with', otherAffectedAddresses), // handle contract transfers\n );\n }\n } else {\n // Make sure to always show the user's address in the details.\n genericDetails.items.push(addressItem('Account', params.account));\n }\n\n isSimulationSuccessful = true;\n } else {\n // If Blockaid simulation fails, we fall back to parsing the transaction manually.\n const { balanceChange: parsedBalanceChange, details: parsedDetails } = await parseTransaction(\n params.transactionBase64,\n params.account,\n network,\n provider,\n );\n balanceChange = parsedBalanceChange;\n details.push(...parsedDetails);\n }\n\n return {\n isSimulationSuccessful,\n details,\n alert,\n balanceChange,\n };\n};\n","import { AlertType, type Alert } from '@avalabs/vm-module-types';\nimport type { MessageScanResponse } from '@blockaid/client/resources/solana/message';\n\nexport const getAlertForError = (error: MessageScanResponse['error_details']): Alert => {\n if (error?.type === 'InstructionError') {\n switch (error.code) {\n case 'ResultWithNegativeLamports':\n return {\n type: AlertType.WARNING,\n details: {\n title: 'This transaction will likely be reverted',\n description: 'Your account does not have enough SOL to perform the operation',\n },\n };\n }\n }\n\n return {\n type: AlertType.WARNING,\n details: {\n title: 'Transaction simulation has failed',\n description: 'It is possible that this transaction will fail. Please proceed with caution.',\n },\n };\n};\n\nexport const transactionAlerts = {\n [AlertType.WARNING]: {\n type: AlertType.WARNING,\n details: {\n title: 'Suspicious Transaction',\n description: 'Use caution, this transaction may be malicious.',\n },\n },\n [AlertType.DANGER]: {\n type: AlertType.DANGER,\n details: {\n title: 'Scam Transaction',\n description: 'This transaction is malicious, do not proceed.',\n actionTitles: {\n reject: 'Reject Transaction',\n proceed: 'Proceed Anyway',\n },\n },\n },\n};\n","import type { BalanceChange, Network, SPLToken } from '@avalabs/vm-module-types';\nimport { deserializeTransactionMessage } from '@avalabs/core-wallets-sdk';\n\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { isNotNullish } from '../functional';\nimport type { getProvider } from '../get-provider';\nimport { tryToParseSolTransfer } from './instruction-parsers/sol-transfer';\nimport { tryToParseSPLTransfer } from './instruction-parsers/spl-transfer';\n\nexport const parseTransaction = async (\n serializedTx: string,\n account: string,\n network: Network,\n provider: ReturnType<typeof getProvider>,\n) => {\n const transaction = await deserializeTransactionMessage(serializedTx, provider);\n const balanceChange: BalanceChange = {\n ins: [],\n outs: [],\n };\n\n const details = await Promise.allSettled(\n transaction.instructions.map(async (instruction) => {\n return (\n tryToParseSolTransfer(instruction, balanceChange, account, network.networkToken) ??\n (await tryToParseSPLTransfer(provider, instruction, balanceChange, account, network.tokens as SPLToken[])) ??\n null\n );\n }),\n ).then((results) =>\n results\n .filter(isFulfilled)\n .map((result) => result.value)\n .filter(isNotNullish),\n );\n\n return {\n balanceChange,\n details,\n };\n};\n","import type { BalanceChange } from '@avalabs/vm-module-types';\n\nexport function isBalanceChangeEmpty(input: BalanceChange): boolean {\n return input.ins.length === 0 && input.outs.length === 0;\n}\n\nexport function isNotNullish<I>(input: I): input is NonNullable<I> {\n return input !== null && input !== undefined;\n}\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { BalanceChange, DetailSection, NetworkToken } from '@avalabs/vm-module-types';\nimport {\n identifySystemInstruction,\n parseTransferSolInstruction,\n SYSTEM_PROGRAM_ADDRESS,\n SystemInstruction,\n} from '@solana-program/system';\nimport {\n isInstructionForProgram,\n isInstructionWithAccounts,\n isInstructionWithData,\n type IInstruction,\n} from '@solana/kit';\n\nimport { addressItem } from '@internal/utils';\n\nexport const tryToParseSolTransfer = (\n instruction: IInstruction,\n balanceChange: BalanceChange,\n account: string,\n networkToken: NetworkToken,\n): DetailSection | null => {\n if (\n !isInstructionForProgram(instruction, SYSTEM_PROGRAM_ADDRESS) ||\n !isInstructionWithAccounts(instruction) ||\n !isInstructionWithData(instruction)\n ) {\n return null;\n }\n\n try {\n const systemInstruction = identifySystemInstruction(instruction);\n\n if (systemInstruction !== SystemInstruction.TransferSol) {\n return null;\n }\n\n const { accounts, data } = parseTransferSolInstruction({\n ...instruction,\n data: Uint8Array.from(instruction.data), // Fixing the typings here to satisfy parseTransferSolInstruction()\n });\n\n const isOutgoing = accounts.source.address === account;\n const balanceChangeKey = isOutgoing === true ? 'outs' : 'ins';\n\n balanceChange[balanceChangeKey].push({\n token: {\n ...networkToken,\n address: '',\n },\n items: [\n {\n displayValue: new TokenUnit(data.amount, networkToken.decimals, '').toString(),\n usdPrice: undefined,\n },\n ],\n });\n\n return {\n title: 'Transfer SOL',\n items: [addressItem('From', accounts.source.address), addressItem('To', accounts.destination.address)],\n };\n } catch {\n return null;\n }\n};\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { SolanaProvider } from '@avalabs/core-wallets-sdk';\nimport type { BalanceChange, DetailSection, SPLToken } from '@avalabs/vm-module-types';\nimport {\n parseTransferInstruction,\n identifyTokenInstruction,\n TokenInstruction,\n parseTransferCheckedInstruction,\n} from '@solana-program/token';\nimport { isInstructionWithAccounts, isInstructionWithData, type Address, type IInstruction } from '@solana/kit';\n\nimport { addressItem } from '@internal/utils';\n\nconst getTokenMintFromAccountInfo = async (provider: SolanaProvider, account: Address): Promise<string | null> => {\n try {\n const tokenAccountDetails = await provider.getAccountInfo(account, { encoding: 'jsonParsed' }).send();\n\n if (Array.isArray(tokenAccountDetails.value?.data)) {\n return null;\n }\n\n const info = tokenAccountDetails.value?.data.parsed.info as Record<string, unknown>;\n return typeof info?.mint === 'string' ? info.mint : null;\n } catch {\n return null;\n }\n};\n\nexport const tryToParseSPLTransfer = async (\n provider: SolanaProvider,\n instruction: IInstruction,\n balanceChange: BalanceChange,\n account: string,\n tokens?: SPLToken[],\n): Promise<DetailSection | null> => {\n if (!tokens?.length || !isInstructionWithAccounts(instruction) || !isInstructionWithData(instruction)) {\n return null;\n }\n\n try {\n const tokenInstruction = identifyTokenInstruction(instruction);\n\n if (tokenInstruction !== TokenInstruction.Transfer && tokenInstruction !== TokenInstruction.TransferChecked) {\n return null;\n }\n\n const parser =\n tokenInstruction === TokenInstruction.TransferChecked\n ? parseTransferCheckedInstruction\n : parseTransferInstruction;\n\n const { accounts, data } = parser({\n ...instruction,\n data: Uint8Array.from(instruction.data), // Fixing the typings here to satisfy parseTransferInstruction()\n });\n const tokenMint = await getTokenMintFromAccountInfo(provider, accounts.source.address);\n\n if (!tokenMint) {\n return null;\n }\n\n const token = tokens.find((t) => t.address.toLowerCase() === tokenMint.toLowerCase());\n\n if (!token) {\n return null;\n }\n\n const isOutgoing = accounts.source.address === account || accounts.authority.address === account;\n const balanceChangeKey = isOutgoing === true ? 'outs' : 'ins';\n const decimals = 'decimals' in data ? data.decimals : token.decimals;\n\n balanceChange[balanceChangeKey].push({\n token,\n items: [\n {\n displayValue: new TokenUnit(data.amount, decimals, '').toString(),\n usdPrice: undefined,\n },\n ],\n });\n\n return {\n title: `Transfer ${token.symbol}`,\n items: [addressItem('From', accounts.source.address), addressItem('To', accounts.destination.address)],\n };\n } catch {\n return null;\n }\n};\n","import type Blockaid from '@blockaid/client';\nimport {\n TokenType,\n type BalanceChange,\n type Network,\n type NetworkToken,\n type SPLToken,\n type TokenDiff,\n} from '@avalabs/vm-module-types';\n\n// Simplify access to Blockaid's typings\ntype SolanaSimulation = Blockaid.Solana.MessageScanResponse.Result.Simulation;\ntype AccountSummaryAssetDiff = SolanaSimulation['account_summary']['account_assets_diff'];\ntype SolanaSimulationAsset = Exclude<AccountSummaryAssetDiff, undefined>[number]['asset'];\n\nexport const processBalanceChange = (\n account: string,\n simulationResult: Blockaid.Solana.Message.MessageScanResponse.Result.Simulation,\n network: Network,\n): { balanceChange: BalanceChange; otherAffectedAddresses: string[] } => {\n const transferedAssets = simulationResult.account_summary.account_assets_diff ?? [];\n\n const inTokenDiffDict: Record<string, TokenDiff> = {};\n const outTokenDiffDict: Record<string, TokenDiff> = {};\n\n const otherAffectedAddresses: string[] = Object.keys(simulationResult.assets_diff ?? {}).filter(\n (key) => key !== account,\n );\n\n transferedAssets.forEach(({ asset, in: assetIn, out: assetOut }) => {\n const token = convertDiffAssetToToken(asset, network);\n\n if (!token) {\n return;\n }\n\n const identifier = 'address' in token ? token.address : token.symbol;\n\n if (assetIn) {\n if (!inTokenDiffDict[identifier]) {\n inTokenDiffDict[identifier] = {\n token,\n items: [],\n };\n }\n\n inTokenDiffDict[identifier].items.push({\n displayValue: String(assetIn.value),\n usdPrice: typeof assetIn.usd_price === 'number' ? String(assetIn.usd_price) : undefined,\n });\n }\n\n if (assetOut) {\n if (!outTokenDiffDict[identifier]) {\n outTokenDiffDict[identifier] = {\n token,\n items: [],\n };\n }\n outTokenDiffDict[identifier].items.push({\n displayValue: String(assetOut.value),\n usdPrice: typeof assetOut.usd_price === 'number' ? String(assetOut.usd_price) : undefined,\n });\n }\n });\n\n return {\n balanceChange: {\n ins: Object.values(inTokenDiffDict),\n outs: Object.values(outTokenDiffDict),\n },\n otherAffectedAddresses,\n };\n};\n\nconst convertNativeAssetToToken = (\n asset: Blockaid.Solana.MessageScanResponse.Result.Simulation.SolanaNativeAssetDiff.Asset,\n): NetworkToken => {\n return {\n name: asset.type,\n symbol: asset.type, // It's either SOL or ETH according to types\n decimals: asset.decimals,\n description: '',\n logoUri: asset.logo ?? undefined,\n };\n};\n\nconst convertTokenAssetToToken = (\n asset: Blockaid.Solana.MessageScanResponse.Result.Simulation.SolanaSplFungibleAssetDiff.Asset,\n network: Network,\n): SPLToken => ({\n type: TokenType.SPL,\n address: asset.address,\n caip2Id: network.caipId ?? '',\n contractType: TokenType.SPL,\n decimals: asset.decimals,\n name: asset.name,\n symbol: asset.symbol,\n logoUri: asset.logo || undefined,\n});\n\nconst convertDiffAssetToToken = (asset: SolanaSimulationAsset, network: Network): SPLToken | NetworkToken | null => {\n if (asset.type === 'TOKEN') {\n return convertTokenAssetToToken(asset, network);\n }\n\n if (asset.type === 'SOL' || asset.type === 'ETH') {\n return convertNativeAssetToToken(asset);\n }\n\n return null;\n};\n","import Blockaid from '@blockaid/client';\nimport { base58, base64 } from '@scure/base';\n\nimport type { ExplainTxParams } from '../types';\n\nexport const scanSolanaTransaction = async ({\n params,\n dAppUrl,\n blockaid,\n}: ExplainTxParams): Promise<Blockaid.Solana.Message.MessageScanResponse | null> => {\n try {\n return await blockaid.solana.message.scan({\n chain: params.chain,\n options: ['simulation', 'validation'],\n encoding: 'base64',\n metadata: {\n url: dAppUrl,\n },\n transactions: [params.transactionBase64],\n // We need to encode the account address to base64 as well\n account_address: base64.encode(base58.decode(params.account)),\n });\n } catch (err) {\n console.error('solana.message.scan() error', err);\n return null;\n }\n};\n","import type { ApprovalController, Network, RpcRequest } from '@avalabs/vm-module-types';\nimport type { getProvider } from './get-provider';\nimport { signature } from '@solana/kit';\nimport { getExplorerAddressByNetwork } from './get-explorer-address-by-network';\n\nconst POLLING_INTERVAL = 400; // Match Solana's block time\nconst MAX_RETRIES = 15; // ~6 seconds total - handle network congestion\n\nexport type WaitForTransactionConfirmationParams = {\n provider: ReturnType<typeof getProvider>;\n txHash: string;\n approvalController: ApprovalController;\n request: RpcRequest;\n network: Network;\n commitment?: 'processed' | 'confirmed' | 'finalized';\n maxRetries?: number;\n};\n\nexport const waitForTransactionConfirmation = async ({\n provider,\n txHash,\n approvalController,\n request,\n network,\n commitment = 'confirmed',\n maxRetries = MAX_RETRIES,\n}: WaitForTransactionConfirmationParams): Promise<boolean> => {\n let retries = 0;\n let lastStatus: string | null = null;\n const explorerLink = getExplorerAddressByNetwork(network, txHash, 'tx');\n\n while (retries < maxRetries) {\n try {\n const response = await provider\n .getSignatureStatuses([signature(txHash)], { searchTransactionHistory: true })\n .send();\n\n if (!response?.value?.[0]) {\n await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));\n retries++;\n continue;\n }\n\n const { confirmationStatus, err } = response.value[0];\n\n if (err) {\n console.error('[waitForTransactionConfirmation] Transaction failed:', err);\n approvalController.onTransactionReverted({ txHash, request });\n return false;\n }\n\n if (confirmationStatus && confirmationStatus !== lastStatus) {\n lastStatus = confirmationStatus;\n\n if (confirmationStatus === 'processed') {\n approvalController.onTransactionPending({ txHash, request });\n }\n\n const isConfirmed =\n (commitment === 'processed' && confirmationStatus === 'processed') ||\n (commitment === 'confirmed' && ['confirmed', 'finalized'].includes(confirmationStatus)) ||\n (commitment === 'finalized' && confirmationStatus === 'finalized');\n\n if (isConfirmed) {\n approvalController.onTransactionConfirmed({ txHash, request, explorerLink });\n return true;\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));\n retries++;\n } catch (error) {\n if (error instanceof Error && error.message.includes('Transaction failed')) {\n console.error('[waitForTransactionConfirmation] Transaction explicitly failed');\n approvalController.onTransactionReverted({ txHash, request });\n return false;\n }\n await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));\n retries++;\n }\n }\n\n // If we reach max retries but had a valid status, don't mark as reverted\n if (lastStatus === 'confirmed' || lastStatus === 'finalized') {\n approvalController.onTransactionConfirmed({ txHash, request, explorerLink });\n return true;\n }\n\n approvalController.onTransactionReverted({ txHash, request });\n return false;\n};\n","import type { Network } from '@avalabs/vm-module-types';\n\nconst fallbackExplorerUrl = 'https://explorer.solana.com';\n\nexport function getExplorerAddressByNetwork(network: Network, hash: string, hashType: 'address' | 'tx' = 'tx') {\n try {\n // Try to respect any query params set on {network.explorerUrl}\n const baseUrl = network.explorerUrl ? new URL(network.explorerUrl) : new URL(fallbackExplorerUrl);\n baseUrl.pathname += `${hashType}/${hash}`;\n return baseUrl.toString();\n } catch {\n return `${network.explorerUrl}/${hashType}/${hash}`;\n }\n}\n","import { z } from 'zod';\n\nconst transactionSchema = z.object({\n account: z.string(),\n serializedTx: z.string().base64(),\n sendOptions: z\n .object({\n preflightCommitment: z.enum(['processed', 'confirmed', 'finalized']).optional(),\n maxRetries: z.bigint().optional(),\n minContextSlot: z.bigint().optional(),\n skipPreflight: z.boolean().optional(),\n })\n .optional(),\n});\n\nconst paramsSchema = z.tuple([transactionSchema]);\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type TransactionParams = z.infer<typeof transactionSchema>;\nexport type SendOptions = z.infer<typeof transactionSchema>['sendOptions'];\n","import { rpcErrors } from '@metamask/rpc-errors';\nimport {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { isBalanceChangeEmpty } from '@src/utils/functional';\nimport { getNetworkName } from '@src/utils/get-network-name';\nimport { explainTransaction } from '@src/utils/explain/explain-transaction';\n\nimport { parseRequestParams } from './schema';\nimport type Blockaid from '@blockaid/client';\n\nexport const signTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n blockaid,\n}: {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n blockaid: Blockaid;\n}) => {\n const { params } = request;\n const { data, success, error } = parseRequestParams(params);\n\n if (!success) {\n console.error('invalid params', error);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: error } }),\n };\n }\n\n const [{ account, serializedTx }] = data;\n\n const provider = getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { details, isSimulationSuccessful, alert, balanceChange } = await explainTransaction({\n simulationParams: {\n dAppUrl: request.dappInfo.url,\n params: {\n account,\n chain: getNetworkName(network),\n transactionBase64: serializedTx,\n },\n blockaid,\n },\n network,\n provider,\n });\n\n const displayData: DisplayData = {\n title: 'Do you approve this transaction?',\n network: {\n chainId: network.chainId,\n name: network.chainName,\n logoUri: network.logoUri,\n },\n details,\n alert,\n balanceChange: balanceChange && isBalanceChangeEmpty(balanceChange) ? undefined : balanceChange,\n networkFeeSelector: false,\n isSimulationSuccessful,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.SOLANA_SIGN_TRANSACTION,\n account,\n data: serializedTx,\n };\n\n const response = await approvalController.requestApproval({ request, displayData, signingData });\n\n if ('error' in response) {\n return {\n error: response.error,\n };\n }\n\n if (!('signedData' in response)) {\n return {\n error: rpcErrors.invalidRequest('No signed data returned'),\n };\n }\n\n return { result: response.signedData };\n};\n","import { z } from 'zod';\n\nconst transactionSchema = z.object({\n account: z.string(),\n serializedTx: z.string().base64(),\n});\n\nconst paramsSchema = z.tuple([transactionSchema]);\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type TransactionParams = z.infer<typeof transactionSchema>;\n","import { rpcErrors } from '@metamask/rpc-errors';\nimport {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\nimport { base64 } from '@scure/base';\n\nimport { addressItem, dataItem, textItem } from '@internal/utils';\n\nimport { parseRequestParams } from './schema';\n\nexport const signMessage = async ({\n request,\n network,\n approvalController,\n}: {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n}) => {\n const { params } = request;\n const { data, success, error } = parseRequestParams(params);\n\n if (!success) {\n console.error('invalid params', error);\n return {\n error: rpcErrors.invalidParams({ message: 'Message signing params are invalid', data: { cause: error } }),\n };\n }\n\n const [{ account, serializedMessage }] = data;\n\n const utf8Decoder = new TextDecoder();\n const displayData: DisplayData = {\n title: 'Sign Message',\n network: {\n chainId: network.chainId,\n name: network.chainName,\n logoUri: network.logoUri,\n },\n dAppInfo: {\n name: request.dappInfo.name,\n action: `${request.dappInfo.name} is requesting to sign the following message`,\n logoUri: request.dappInfo.icon,\n },\n details: [\n {\n title: 'Message Details',\n items: [\n addressItem('Account', account),\n textItem('Message', utf8Decoder.decode(base64.decode(serializedMessage))),\n dataItem('Raw Message (Base-64)', serializedMessage),\n ],\n },\n ],\n networkFeeSelector: false,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.SOLANA_SIGN_MESSAGE,\n account,\n data: serializedMessage,\n };\n\n const response = await approvalController.requestApproval({ request, displayData, signingData });\n\n if ('error' in response) {\n return {\n error: response.error,\n };\n }\n\n if (!('signedData' in response)) {\n return {\n error: rpcErrors.invalidRequest('No signed data returned'),\n };\n }\n\n return { result: response.signedData };\n};\n","import { base64 } from '@scure/base';\nimport { getCompiledTransactionMessageDecoder } from '@solana/kit';\n\nexport const isTransactionBytes = (base64Payload: string): boolean => {\n try {\n const bytes = base64.decode(base64Payload);\n const decoder = getCompiledTransactionMessageDecoder();\n decoder.decode(bytes);\n return true;\n } catch {\n return false;\n }\n};\n","import { isTransactionBytes } from '@src/utils/is-transaction-bytes';\nimport { z } from 'zod';\n\nconst signMessageSchema = z\n .object({\n account: z.string(),\n serializedMessage: z.string().base64(),\n })\n .refine(({ serializedMessage }) => !isTransactionBytes(serializedMessage), {\n message: 'Cannot use signMessage() calls for signing transactions',\n });\n\nconst paramsSchema = z.tuple([signMessageSchema]);\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type SignMessageParams = z.infer<typeof signMessageSchema>;\n"]}
1
+ {"version":3,"sources":["../src/module.ts","../../../packages-internal/utils/src/services/token-service/token-service.ts","../../../packages-internal/utils/src/utils/retry.ts","../../../packages-internal/utils/src/utils/coingecko-retry.ts","../../../packages-internal/utils/src/utils/charsum.ts","../../../packages-internal/utils/src/utils/array-hash.ts","../../../packages-internal/utils/src/services/token-service/coingecko-proxy-client.ts","../../../packages-internal/utils/src/utils/fetch-and-verify.ts","../../../packages-internal/utils/src/services/token-service/watchlist-proxy-client.ts","../../../packages-internal/utils/src/services/pricing-service/exchange-rates.ts","../../../packages-internal/utils/src/utils/detail-item.ts","../../../packages-internal/utils/src/utils/get-core-headers.ts","../../../packages-internal/utils/src/consts.ts","../../../packages-internal/utils/src/utils/get-glacier-api-key.ts","../../../packages-internal/utils/src/utils/glacier-fetch-http-request.ts","../manifest.json","../src/env.ts","../src/handlers/derive-address/derive-address.ts","../../../packages-internal/utils/src/utils/address-derivation.ts","../src/handlers/build-derivation-path/build-derivation-path.ts","../src/handlers/get-network-fee/get-network-fee.ts","../src/utils/get-provider.ts","../src/constants.ts","../src/handlers/get-tokens/get-tokens.ts","../src/handlers/get-tokens/spl-token-schema.ts","../src/handlers/get-balances/get-balances.ts","../src/utils/moralis-service/moralis-schemas.ts","../src/utils/moralis-service/moralis-service.ts","../src/utils/get-network-name.ts","../src/handlers/get-transaction-history/get-transaction-history.ts","../src/handlers/get-transaction-history/extract-transfer.ts","../src/handlers/get-transaction-history/get-wrapped-transactions.ts","../../../packages-internal/utils/src/utils/is-promise-fulfilled.ts","../src/utils/has-property-defined.ts","../src/handlers/get-transaction-history/get-explorer-link.ts","../src/handlers/sign-and-send-transaction/sign-and-send-transaction.ts","../src/utils/explain/explain-transaction.ts","../src/utils/transaction-alerts.ts","../src/utils/explain/parse-transaction.ts","../src/utils/functional.ts","../src/utils/explain/instruction-parsers/sol-transfer.ts","../src/utils/explain/instruction-parsers/spl-transfer.ts","../src/utils/explain/blockaid/process-balance-change.ts","../src/utils/explain/blockaid/scan-solana-transaction.ts","../src/utils/wait-for-transaction-confirmation.ts","../src/utils/get-explorer-address-by-network.ts","../src/handlers/sign-and-send-transaction/schema.ts","../src/handlers/sign-transaction/sign-transaction.ts","../src/handlers/sign-transaction/schema.ts","../src/handlers/sign-message/sign-message.ts","../src/utils/is-transaction-bytes.ts","../src/handlers/sign-message/schema.ts"],"names":["parseManifest","RpcMethod","rpcErrors","VsCurrencyType","getBasicCoingeckoHttp","simplePrice","simpleTokenPrice","retry","operation","isSuccess","maxRetries","backoffPolicy","RetryBackoffPolicy","backoffPeriodMillis","retries","lastError","delay","result","err","errorMessage","retryIndex","secondsToDelay","_","msToDelay","linearCount","linearStepMs","n","base","incSum","ms","r","coingeckoRetry","response","charsum","s","i","sum","arrayHash","array","cs","RawSimplePriceResponseSchema","fetchAndVerify","fetchOptions","schema","responseJson","CoingeckoProxyClient","proxyApiUrl","params","queryParams","id","rawQueryParams","z","WatchlistTokenResponseSchema","WatchlistProxyClient","coingeckoBasicClient","_storage","_proxyApiUrl","TokenService","storage","__privateAdd","__publicField","data","currencies","formattedData","tokenData","currency","__privateSet","tokenDetails","tokenInfo","__privateGet","token","coinIds","cacheId","useCoingeckoProxy","tokenAddresses","assetPlatformId","rawData","marketCap","vol24","change24","lastUpdated","shouldThrow","number","object","record","string","ExchangeRateSchema","DetailItemType","textItem","label","value","alignment","addressItem","addressListItem","dataItem","AppName","GLACIER_API_KEY","getGlacierApiKey","GLOBAL_QUERY_PARAMS","manifest_default","Environment","prodEnv","devEnv","getEnv","environment","NetworkVMType","base58","hex","hasDerivationDetails","buildDerivationPath","accountIndex","deriveAddress","approvalController","secretId","derivationPath","publicKeyHex","getSolanaProvider","SOLANA_MAINNET_CAIP2_ID","SOLANA_DEVNET_CAIP2_ID","SOLANA_TESTNET_CAIP2_ID","RPC_URL_PROXY_API_ENDPOINT","RPC_URL_DEVNET","BLOCKAID_API_KEY","getProvider","isTestnet","LamportsMultiplier","DEFAULT_PRIORITY_FEE","ensureEnoughData","fees","a","b","getNetworkFee","network","feesRaw","block","sortedFees","minFeeInRecentBlocks","maxFeeInRecentBlocks","midIndex","medianFee","presetHigh","presetMedium","presetLow","TokenType","SPL_TOKEN_SCHEMA","SPL_TOKENS_SCHEMA","getTokens","caip2Id","error","TokenUnit","PORTFOLIO_SCHEMA","_baseUrl","_buildUrl","buildUrl_fn","MoralisService","address","url","__privateMethod","portfolio","message","path","getNetworkName","getBalances","addresses","tokenService","moralisService","coingeckoAssetId","coingeckoPlatformId","lowercaseCurrency","solanaNetwork","portfolioResults","mints","mint","tokenPrices","nativeMarketData","portfolioAcc","nativeBalanceUnit","nativeBalanceInCurrency","solanaBalance","tokenBalances","tokensAcc","amountRaw","symbol","decimals","name","logo","balanceUnit","marketData","getMarketData","balanceInCurrency","coinIdOrAddress","prices","TransactionType","simplifyTokenBalance","balance","extractTokenTranfers","meta","ourAddress","preBalances","acc","owner","amount","transfers","key","preAmount","netChange","isReceive","isSend","sender","k","possibleSender","mintFromPreBalance","preBalance","postBalance","postMint","t","transfer","recipient","postBalanceOwner","postBalanceMint","p","nativeTransfer","extractNativeTransfer","paidFee","postBalances","splTransfers","ourAccountIndex","addr","nativeBalancePre","rawBalanceChange","solSpent","unit","largestSOLRecipient","max","diff","balanceDiffs","isSwapContext","nativeTransferAmount","isIncoming","counterpartyIndex","isSOLtoSPLSwap","receivedSPL","sentSPL","largestGainer","largestBeneficiary","index","change","counterpartyAddress","fromAddress","toAddress","solAddress","isFulfilled","hasPropertyDefined","thing","getWrappedTransactions","provider","mainSignatures","sig","allSignatures","networkName","portfolioResult","tokenATAs","nftATAs","nft","ataSignaturePromises","ataAddress","ataSignatures","tx","getExplorerLink","txHash","baseUrl","explorerLink","getTransactionHistory","isOurAddressInTransaction","isSigner","txType","inferTxType","ourTransfers","hasSending","hasReceiving","AlertType","getAlertForError","transactionAlerts","deserializeTransactionMessage","isBalanceChangeEmpty","input","isNotNullish","identifySystemInstruction","parseTransferSolInstruction","SYSTEM_PROGRAM_ADDRESS","SystemInstruction","isInstructionForProgram","isInstructionWithAccounts","isInstructionWithData","tryToParseSolTransfer","instruction","balanceChange","account","networkToken","accounts","balanceChangeKey","parseTransferInstruction","identifyTokenInstruction","TokenInstruction","parseTransferCheckedInstruction","getTokenMintFromAccountInfo","tokenAccountDetails","info","tryToParseSPLTransfer","tokens","tokenInstruction","parser","tokenMint","parseTransaction","serializedTx","transaction","details","results","processBalanceChange","simulationResult","transferedAssets","inTokenDiffDict","outTokenDiffDict","otherAffectedAddresses","asset","assetIn","assetOut","convertDiffAssetToToken","identifier","convertNativeAssetToToken","convertTokenAssetToToken","base64","scanSolanaTransaction","dAppUrl","blockaid","explainTransaction","simulationParams","scanResponse","simulation","validation","genericDetails","isSimulationSuccessful","alert","processedBalanceChange","accountAssetsDiff","outgoingAssets","incomingAssets","parsedBalanceChange","parsedDetails","signature","fallbackExplorerUrl","getExplorerAddressByNetwork","hash","hashType","POLLING_INTERVAL","MAX_RETRIES","waitForTransactionConfirmation","request","commitment","lastStatus","resolve","confirmationStatus","transactionSchema","paramsSchema","parseRequestParams","signAndSendTransaction","success","sendOptions","displayData","signingData","getTxHash","signTransaction","getCompiledTransactionMessageDecoder","isTransactionBytes","base64Payload","bytes","signMessageSchema","serializedMessage","signMessage","utf8Decoder","Blockaid","_approvalController","_appInfo","_blockaid","SvmModule","appInfo","runtime"],"mappings":"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","sourcesContent":["import {\n parseManifest,\n RpcMethod,\n type AppInfo,\n type ApprovalController,\n type BuildDerivationPathParams,\n type ConstructorParams,\n type DeriveAddressParams,\n type GetBalancesParams,\n type GetTransactionHistory,\n type Module,\n type Network,\n type NetworkFeeParam,\n type RpcRequest,\n} from '@avalabs/vm-module-types';\nimport type { SolanaProvider } from '@avalabs/core-wallets-sdk';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\nimport { TokenService } from '@internal/utils';\n\nimport ManifestJson from '../manifest.json';\nimport { getEnv } from './env';\nimport { deriveAddress } from './handlers/derive-address';\nimport { buildDerivationPath } from './handlers/build-derivation-path';\nimport { getNetworkFee } from './handlers/get-network-fee';\nimport { getTokens } from './handlers/get-tokens';\nimport { getBalances } from './handlers/get-balances';\nimport { getProvider } from './utils/get-provider';\nimport { getTransactionHistory } from './handlers/get-transaction-history';\nimport { signAndSendTransaction } from './handlers/sign-and-send-transaction';\nimport { signTransaction } from './handlers/sign-transaction';\nimport { signMessage } from './handlers/sign-message';\nimport Blockaid from '@blockaid/client';\nimport { BLOCKAID_API_KEY } from './constants';\n\nexport class SvmModule implements Module {\n #proxyApiUrl: string;\n #approvalController: ApprovalController;\n #appInfo: AppInfo;\n #blockaid: Blockaid;\n\n constructor({ approvalController, environment, appInfo, runtime }: ConstructorParams) {\n const { proxyApiUrl } = getEnv(environment);\n\n this.#appInfo = appInfo;\n this.#proxyApiUrl = proxyApiUrl;\n this.#approvalController = approvalController;\n\n // Temporarily referencing those props here just to silence eslint,\n // as eslint-disable-... comments don't seem to work on class properties.\n this.#proxyApiUrl;\n this.#approvalController;\n this.#appInfo;\n this.#blockaid = new Blockaid({\n baseURL: proxyApiUrl + '/proxy/blockaid/',\n apiKey: BLOCKAID_API_KEY,\n httpAgent: runtime?.httpAgent,\n fetch: runtime?.fetch,\n });\n }\n\n async getProvider(network: Network): Promise<SolanaProvider> {\n return getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl: this.#proxyApiUrl });\n }\n\n // TODO\n getAddress() {\n return Promise.resolve({});\n }\n\n buildDerivationPath(params: BuildDerivationPathParams) {\n return buildDerivationPath(params);\n }\n\n deriveAddress(params: DeriveAddressParams) {\n return deriveAddress({\n ...params,\n approvalController: this.#approvalController,\n });\n }\n\n getBalances(params: GetBalancesParams) {\n const tokenService = new TokenService({ storage: params.storage, proxyApiUrl: this.#proxyApiUrl });\n\n return getBalances({\n ...params,\n tokenService,\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getManifest() {\n const result = parseManifest(ManifestJson);\n return result.success ? result.data : undefined;\n }\n\n getNetworkFee(network: NetworkFeeParam) {\n return getNetworkFee(network, this.#proxyApiUrl);\n }\n\n getTransactionHistory(params: GetTransactionHistory) {\n return getTransactionHistory({\n network: params.network,\n address: params.address,\n proxyApiUrl: this.#proxyApiUrl,\n });\n }\n\n getTokens(network: Network) {\n if (!network.caipId) {\n return Promise.reject({ error: rpcErrors.invalidParams(`Network must have a CAIP-2 id`) });\n }\n\n return getTokens({ caip2Id: network.caipId, proxyApiUrl: this.#proxyApiUrl });\n }\n\n // TODO\n async onRpcRequest(request: RpcRequest, network: Network) {\n switch (request.method) {\n case RpcMethod.SOLANA_SIGN_TRANSACTION: {\n return signTransaction({\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n network,\n request,\n blockaid: this.#blockaid,\n });\n }\n case RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION: {\n return signAndSendTransaction({\n approvalController: this.#approvalController,\n proxyApiUrl: this.#proxyApiUrl,\n network,\n request,\n blockaid: this.#blockaid,\n });\n }\n case RpcMethod.SOLANA_SIGN_MESSAGE: {\n return signMessage({\n approvalController: this.#approvalController,\n network,\n request,\n });\n }\n }\n return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };\n }\n}\n","import {\n VsCurrencyType,\n getBasicCoingeckoHttp,\n simplePrice,\n simpleTokenPrice,\n type SimplePriceParams,\n} from '@avalabs/core-coingecko-sdk';\nimport type { Storage, RawSimplePriceResponse, SimplePriceResponse } from '@avalabs/vm-module-types';\nimport { coingeckoRetry } from '../../utils/coingecko-retry';\nimport { arrayHash } from '../../utils/array-hash';\nimport { CoingeckoProxyClient } from './coingecko-proxy-client';\nimport { WatchlistProxyClient } from './watchlist-proxy-client';\n\nconst coingeckoBasicClient = getBasicCoingeckoHttp();\n\nexport class TokenService {\n #storage?: Storage;\n #proxyApiUrl: string;\n\n constructor({ storage, proxyApiUrl }: { proxyApiUrl: string; storage?: Storage }) {\n this.#storage = storage;\n this.#proxyApiUrl = proxyApiUrl;\n }\n\n async getWatchlistDataForToken({\n tokenDetails,\n currency = VsCurrencyType.USD,\n }: {\n tokenDetails: {\n symbol: string;\n isNative: boolean;\n caip2Id: string;\n address?: string;\n };\n currency: VsCurrencyType;\n }): Promise<{\n priceInCurrency: number;\n change24: number;\n marketCap: number;\n vol24: number;\n }> {\n const data = (\n await new WatchlistProxyClient(this.#proxyApiUrl).watchlistToken({\n tokens: tokenDetails.symbol,\n currency: currency,\n })\n ).filter((token) => {\n return tokenDetails.isNative\n ? token.internalId === `NATIVE-${tokenDetails.symbol.toLowerCase()}`\n : token.platforms[tokenDetails.caip2Id] === tokenDetails.address;\n });\n\n const tokenInfo = data[0];\n\n if (!tokenInfo) {\n return {\n priceInCurrency: 0,\n change24: 0,\n marketCap: 0,\n vol24: 0,\n };\n }\n\n return {\n priceInCurrency: tokenInfo.current_price ?? 0,\n change24: tokenInfo.price_change_percentage_24h ?? 0,\n marketCap: tokenInfo.market_cap ?? 0,\n vol24: tokenInfo.total_volume ?? 0,\n };\n }\n\n /**\n * Get token price with market data first on coingecko (free tier) directly,\n * if we get 429 error, retry it on coingecko proxy (paid service)\n * @returns token price with market data\n */\n async getSimplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n }: SimplePriceParams): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = coinIds ? `${arrayHash(coinIds)}-${currencies.toString()}` : `${currencies.toString()}`;\n\n const cacheId = `getSimplePrice-${key}`;\n\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data) return data;\n\n try {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.simplePrice({\n coinIds,\n currencies,\n marketCap: true,\n vol24: true,\n change24: true,\n useCoingeckoProxy,\n }),\n );\n } catch {\n data = undefined;\n }\n this.#storage?.set?.(cacheId, data);\n return data;\n }\n\n /**\n * Get token price with market data for a list of addresses\n * @param tokenAddresses the token addresses\n * @param assetPlatformId The platform id for all the tokens in the list\n * @param currency the currency to be used\n * @returns a list of token price with market data\n */\n async getPricesByAddresses(\n tokenAddresses: string[],\n assetPlatformId: string,\n currency: VsCurrencyType = VsCurrencyType.USD,\n ): Promise<SimplePriceResponse | undefined> {\n let data: SimplePriceResponse | undefined;\n\n const key = `${arrayHash(tokenAddresses)}-${assetPlatformId}-${currency}`;\n\n const cacheId = `getPricesWithMarketDataByAddresses-${key}`;\n data = this.#storage?.get?.<SimplePriceResponse>(cacheId);\n\n if (data) return data;\n\n try {\n data = await coingeckoRetry((useCoingeckoProxy) =>\n this.fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency,\n useCoingeckoProxy,\n }),\n );\n } catch (err) {\n console.error(err);\n data = undefined;\n }\n this.#storage?.set?.(cacheId, data);\n return data;\n }\n\n private async fetchPricesByAddresses({\n assetPlatformId,\n tokenAddresses,\n currency = VsCurrencyType.USD,\n useCoingeckoProxy = false,\n }: {\n assetPlatformId: string;\n tokenAddresses: string[];\n currency: VsCurrencyType;\n useCoingeckoProxy?: boolean;\n }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n const rawData = await new CoingeckoProxyClient(this.#proxyApiUrl).simplePriceByContractAddresses({\n id: assetPlatformId,\n contract_addresses: tokenAddresses,\n vs_currencies: [currency],\n include_market_cap: true,\n include_24hr_vol: true,\n include_24hr_change: true,\n });\n return this.transformSimplePriceResponse(rawData, [currency]);\n }\n\n return simpleTokenPrice(coingeckoBasicClient, {\n assetPlatformId,\n tokenAddresses,\n currencies: [currency],\n marketCap: true,\n vol24: true,\n change24: true,\n });\n }\n\n private async simplePrice({\n coinIds = [],\n currencies = [VsCurrencyType.USD],\n marketCap = false,\n vol24 = false,\n change24 = false,\n lastUpdated = false,\n useCoingeckoProxy = false,\n shouldThrow = true,\n }: SimplePriceParams & { useCoingeckoProxy?: boolean }): Promise<SimplePriceResponse> {\n if (useCoingeckoProxy) {\n const rawData = await new CoingeckoProxyClient(this.#proxyApiUrl).simplePrice({\n ids: coinIds,\n vs_currencies: currencies,\n include_market_cap: marketCap,\n include_24hr_vol: vol24,\n include_24hr_change: change24,\n include_last_updated_at: lastUpdated,\n });\n return this.transformSimplePriceResponse(rawData, currencies);\n }\n return simplePrice(coingeckoBasicClient, {\n coinIds,\n currencies,\n marketCap,\n vol24,\n change24,\n lastUpdated,\n shouldThrow,\n });\n }\n\n private transformSimplePriceResponse = (\n data: RawSimplePriceResponse,\n currencies = [VsCurrencyType.USD],\n ): SimplePriceResponse => {\n const formattedData: SimplePriceResponse = {};\n Object.keys(data).forEach((id) => {\n const tokenData = data[id];\n formattedData[id] = {};\n currencies.forEach((currency: VsCurrencyType) => {\n formattedData[id] = {\n [currency]: {\n price: tokenData?.[currency],\n change24: tokenData?.[`${currency}_24h_change`],\n vol24: tokenData?.[`${currency}_24h_vol`],\n marketCap: tokenData?.[`${currency}_market_cap`],\n },\n };\n });\n });\n return formattedData;\n };\n}\n","const DEFAULT_MAX_RETRIES = 10;\n\ntype RetryParams<T> = {\n operation: (retryIndex: number) => Promise<T>;\n isSuccess: (result: T) => boolean;\n maxRetries?: number;\n backoffPolicy?: RetryBackoffPolicyInterface;\n};\n/*\n * Retries an operation with defined backoff policy.\n *\n * @param operation - The operation to retry.\n * @param isSuccess - The predicate to check if the operation succeeded.\n * @param maxRetries - The maximum number of retries.\n * @param backoffPolicy - Function to generate delay time based on current retry count.\n *\n * @returns The result of the operation.\n * @throws An error if the operation fails after the maximum number of retries.\n *\n * @example\n * const result = await retry(\n * async () => {\n * const response = await fetch('https://example.com')\n * return response.json()\n * },\n * result => result.status === 200\n * )\n */\nexport const retry = async <T>({\n operation,\n isSuccess,\n maxRetries = DEFAULT_MAX_RETRIES,\n backoffPolicy = RetryBackoffPolicy.exponential(),\n}: RetryParams<T>): Promise<T> => {\n let backoffPeriodMillis = 0;\n let retries = 0;\n let lastError: unknown;\n\n while (retries < maxRetries) {\n if (retries > 0) {\n await delay(backoffPeriodMillis);\n }\n\n try {\n const result = await operation(retries);\n\n if (isSuccess(result)) {\n return result;\n }\n } catch (err) {\n // when the operation throws an error, we still retry\n lastError = err;\n }\n\n backoffPeriodMillis = backoffPolicy(retries);\n retries++;\n }\n\n const errorMessage = lastError ? `Max retry exceeded. ${lastError}` : 'Max retry exceeded.';\n\n throw new Error(errorMessage);\n};\n\ntype RetryBackoffPolicyInterface = (retryIndex: number) => number;\n\nexport class RetryBackoffPolicy {\n static exponential(): RetryBackoffPolicyInterface {\n return (retryIndex: number): number => {\n return Math.pow(2, retryIndex) * 1000;\n };\n }\n\n static constant(secondsToDelay: number): RetryBackoffPolicyInterface {\n return (_: number): number => {\n return secondsToDelay * 1000;\n };\n }\n\n static constantMs(msToDelay: number): RetryBackoffPolicyInterface {\n return (_: number): number => {\n return msToDelay;\n };\n }\n\n /**\n * linearThenExponential backoff:\n * - First `linearCount` retries: linear increase by `linearStepMs`\n * - After that: increment grows exponentially based on `linearStepMs`\n * Example (linearCount=4, linearStepMs=1000):\n * 1s, 2s, 3s, 4s, 6s, 10s, 18s, 34s...\n */\n static linearThenExponential(linearCount: number, linearStepMs: number): RetryBackoffPolicyInterface {\n return (retryIndex: number): number => {\n if (retryIndex < linearCount) {\n // Linear phase: (i+1) * step\n return (retryIndex + 1) * linearStepMs;\n }\n // Exponential-increment phase (closed form):\n // n = number of exponential increments applied\n // base = linearCount * step\n // increment sum = 2*step * (2^n - 1)\n const n = retryIndex - linearCount + 1;\n const base = linearCount * linearStepMs;\n const incSum = 2 * linearStepMs * (Math.pow(2, n) - 1);\n return base + incSum;\n };\n }\n}\n\nfunction delay(ms: number) {\n return new Promise((r) => setTimeout(r, ms));\n}\n","import { RetryBackoffPolicy, retry } from './retry';\n\ntype Error = {\n status: {\n error_code: number;\n error_message: string;\n };\n};\n\nexport const coingeckoRetry = <T>(\n operation: (useCoingeckoProxy: boolean) => Promise<T | Error>,\n): Promise<T | undefined> => {\n return retry({\n operation: (retryIndex: number) => operation(retryIndex > 0),\n maxRetries: 2,\n backoffPolicy: RetryBackoffPolicy.constant(1),\n isSuccess: (response: T | Error) => {\n const errorStatus = (response as Error)?.status;\n return errorStatus?.error_code !== 429;\n },\n }) as Promise<T | undefined>;\n};\n","export function charsum(s: string): number {\n let i,\n sum = 0;\n for (i = 0; i < s.length; i++) {\n sum += s.charCodeAt(i) * (i + 1);\n }\n return sum;\n}\n","import { charsum } from './charsum';\n\n// from https://stackoverflow.com/a/25105589\nexport function arrayHash(array: string[]): string {\n let i,\n sum = 0;\n for (i = 0; i < array.length; i++) {\n const cs = charsum(array[i] ?? '');\n sum = sum + 65027 / cs;\n }\n return ('' + sum).slice(0, 16);\n}\n","import { RawSimplePriceResponseSchema } from '@avalabs/vm-module-types';\nimport { fetchAndVerify } from '../../utils/fetch-and-verify';\n\nexport class CoingeckoProxyClient {\n constructor(private proxyApiUrl: string) {}\n\n simplePrice(params: {\n ids: string[];\n vs_currencies: string[];\n include_market_cap?: boolean;\n include_24hr_vol?: boolean;\n include_24hr_change?: boolean;\n include_last_updated_at?: boolean;\n }) {\n // casting params as any since typing does not allow boolean and other non-string values\n // even though NodeJS does not have this restriction itself: https://nodejs.org/api/url.html#new-urlsearchparamsobj\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const queryParams = new URLSearchParams(params as any);\n return fetchAndVerify(\n [\n `${this.proxyApiUrl}/proxy/coingecko/simple/price?${queryParams}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n RawSimplePriceResponseSchema,\n );\n }\n\n simplePriceByContractAddresses(params: {\n id: string;\n contract_addresses: string[];\n vs_currencies?: string[];\n include_market_cap?: boolean;\n include_24hr_vol?: boolean;\n include_24hr_change?: boolean;\n }) {\n const { id, ...rawQueryParams } = params;\n\n // casting params as any since typing does not allow boolean and other non-string values\n // even though NodeJS does not have this restriction itself: https://nodejs.org/api/url.html#new-urlsearchparamsobj\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const queryParams = new URLSearchParams(rawQueryParams as any);\n\n return fetchAndVerify(\n [\n `${this.proxyApiUrl}/proxy/coingecko/simple/token_price/${id}?${queryParams}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n RawSimplePriceResponseSchema,\n );\n }\n}\n","import z from 'zod';\nimport type { ZodSchema } from 'zod';\n\nexport async function fetchAndVerify<T extends ZodSchema>(\n fetchOptions: Parameters<typeof fetch>,\n schema: T,\n): Promise<z.infer<T>> {\n const response = await fetch(...fetchOptions);\n\n if (!response.ok) {\n throw new Error(`Request failed with status ${response.status}`);\n }\n\n const responseJson = await response.json();\n return schema.parse(responseJson);\n}\n","import { fetchAndVerify } from '../../utils/fetch-and-verify';\nimport { z } from 'zod';\n\nconst WatchlistTokenResponseSchema = z.array(\n z.object({\n // the object has more properties than the ones listed here, but we only need these at the moment\n internalId: z.string(),\n id: z.string(),\n symbol: z.string(),\n name: z.string(),\n image: z.string().optional().nullable(),\n current_price: z.number().optional().nullable(),\n price_change_percentage_24h: z.number().optional().nullable(),\n market_cap: z.number().optional().nullable(),\n total_volume: z.number().optional().nullable(),\n platforms: z.record(z.string(), z.string()),\n }),\n);\n\nexport class WatchlistProxyClient {\n constructor(private proxyApiUrl: string) {}\n\n watchlistToken(params: { tokens: string; currency: string }) {\n // casting params as any since typing does not allow boolean and other non-string values\n // even though NodeJS does not have this restriction itself: https://nodejs.org/api/url.html#new-urlsearchparamsobj\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const queryParams = new URLSearchParams(params as any);\n return fetchAndVerify(\n [\n `${this.proxyApiUrl}/watchlist/tokens?${queryParams}`,\n {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ],\n WatchlistTokenResponseSchema,\n );\n }\n}\n","import z, { number, object, record, string } from 'zod';\nimport { fetchAndVerify } from '../../utils/fetch-and-verify';\n\nconst CURRENCY_EXCHANGE_RATES_URL =\n 'https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/usd.min.json';\n\nconst CURRENCY_EXCHANGE_RATES_FALLBACK_URL = 'https://latest.currency-api.pages.dev/v1/currencies/usd.min.json';\n\nconst ExchangeRateSchema = object({\n date: string(),\n usd: record(number()),\n});\n\ntype ExchangeRate = z.infer<typeof ExchangeRateSchema>;\n\nexport const getExchangeRates = async (): Promise<ExchangeRate> => {\n try {\n return await fetchAndVerify([CURRENCY_EXCHANGE_RATES_URL], ExchangeRateSchema);\n } catch {\n return await fetchAndVerify([CURRENCY_EXCHANGE_RATES_FALLBACK_URL], ExchangeRateSchema);\n }\n};\n","import {\n type AddressItem,\n type CurrencyItem,\n type NodeIDItem,\n type TextItem,\n type DataItem,\n type DateItem,\n type LinkItemValue,\n DetailItemType,\n type LinkItem,\n type FundsRecipientItem,\n type AddressListItem,\n type NetworkItemValue,\n type NetworkItem,\n} from '@avalabs/vm-module-types';\n\nexport const fundsRecipientItem = (\n address: string,\n amount: bigint,\n maxDecimals: number,\n symbol: string,\n): FundsRecipientItem => ({\n type: DetailItemType.FUNDS_RECIPIENT,\n label: address,\n amount,\n maxDecimals,\n symbol,\n});\n\nexport const currencyItem = (label: string, value: bigint, maxDecimals: number, symbol: string): CurrencyItem => ({\n label,\n type: DetailItemType.CURRENCY,\n value,\n maxDecimals,\n symbol,\n});\n\nexport const textItem = (\n label: string,\n value: string,\n alignment: 'horizontal' | 'vertical' = 'horizontal',\n): TextItem => ({\n label,\n alignment,\n type: DetailItemType.TEXT,\n value,\n});\n\nexport const linkItem = (label: string, value: LinkItemValue): LinkItem => ({\n label,\n value,\n type: DetailItemType.LINK,\n});\n\nexport const addressItem = (label: string, value: string): AddressItem => ({\n label,\n type: DetailItemType.ADDRESS,\n value,\n});\n\nexport const addressListItem = (label: string, value: string[]): AddressListItem => ({\n label,\n type: DetailItemType.ADDRESS_LIST,\n value,\n});\n\nexport const nodeIDItem = (label: string, value: string): NodeIDItem => ({\n label,\n type: DetailItemType.NODE_ID,\n value,\n});\n\nexport const dataItem = (label: string, value: string): DataItem => ({\n label,\n type: DetailItemType.DATA,\n value,\n});\n\nexport const dateItem = (label: string, value: string): DateItem => ({\n label,\n type: DetailItemType.DATE,\n value,\n});\n\nexport const networkItem = (label: string, value: NetworkItemValue): NetworkItem => ({\n label,\n type: DetailItemType.NETWORK,\n value,\n});\n","import { AppName, type AppInfo } from '@avalabs/vm-module-types';\n\nexport const getCoreHeaders = ({ name, version }: AppInfo): Record<string, string> | undefined => {\n switch (name) {\n case AppName.CORE_MOBILE_IOS:\n case AppName.CORE_MOBILE_ANDROID:\n case AppName.CORE_WEB:\n case AppName.CORE_EXTENSION:\n case AppName.EXPLORER:\n return {\n 'x-application-name': name,\n 'x-application-version': version,\n };\n case AppName.OTHER:\n return undefined;\n }\n};\n","export const GLACIER_API_KEY = process.env.GLACIER_API_KEY;\n","import { GLACIER_API_KEY } from '../consts';\n\n// this key is only needed in development to bypass rate limit\n// it should never be used in production\nexport const getGlacierApiKey = (): string | undefined => {\n return GLACIER_API_KEY;\n};\n","import { FetchHttpRequest, type OpenAPIConfig, type ApiRequestOptions, CancelablePromise } from '@avalabs/glacier-sdk';\nimport { getGlacierApiKey } from './get-glacier-api-key';\n\nconst GLOBAL_QUERY_PARAMS: Record<string, string | undefined> = {\n rltoken: getGlacierApiKey(),\n};\n\n/**\n * Custom HTTP request handler that automatically appends the Glacier API key (if present)\n * to bypass rate limits in development environments.\n */\nexport class GlacierFetchHttpRequest extends FetchHttpRequest {\n constructor(config: OpenAPIConfig) {\n super(config);\n }\n\n public override request<T>(options: ApiRequestOptions): CancelablePromise<T> {\n // Merge global query parameters with request-specific ones\n const mergedQuery = {\n ...GLOBAL_QUERY_PARAMS,\n ...(options.query || {}), // Request-specific params (override globals if same key)\n };\n\n // Create modified options with merged query\n const modifiedOptions: ApiRequestOptions = {\n ...options,\n query: Object.keys(mergedQuery).length > 0 ? mergedQuery : undefined,\n };\n\n // Call the base class's request method\n return super.request<T>(modifiedOptions);\n }\n}\n","{\n \"name\": \"SVM\",\n \"description\": \"\",\n \"version\": \"0.0.1\",\n \"sources\": {\n \"module\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/index.js\",\n \"packageName\": \"@avalabs/svm-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n },\n \"provider\": {\n \"checksum\": \"\",\n \"location\": {\n \"npm\": {\n \"filePath\": \"dist/provider/index.js\",\n \"packageName\": \"@avalabs/svm-module\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n }\n }\n },\n \"network\": {\n \"chainIds\": [\n \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\"\n ],\n \"namespaces\": [\"solana\"]\n },\n \"cointype\": \"501\",\n \"permissions\": {\n \"rpc\": {\n \"dapps\": true,\n \"methods\": [\"solana_signTransaction\", \"solana_signAndSendTransaction\", \"solana_signMessage\"],\n \"nonRestrictedMethods\": []\n }\n },\n \"manifestVersion\": \"0.1\"\n}\n","import { Environment } from '@avalabs/vm-module-types';\n\ntype Env = {\n proxyApiUrl: string;\n};\n\nexport const prodEnv: Env = {\n proxyApiUrl: 'https://proxy-api.avax.network',\n};\n\nexport const devEnv: Env = {\n proxyApiUrl: 'https://proxy-api-dev.avax.network',\n};\n\nexport const getEnv = (environment: Environment): Env => {\n switch (environment) {\n case Environment.PRODUCTION:\n return prodEnv;\n case Environment.DEV:\n return devEnv;\n }\n};\n","import type { ApprovalController, DeriveAddressParams, DeriveAddressResponse } from '@avalabs/vm-module-types';\nimport { NetworkVMType } from '@avalabs/vm-module-types';\nimport { base58, hex } from '@scure/base';\n\nimport { hasDerivationDetails } from '@internal/utils/src/utils/address-derivation';\nimport { buildDerivationPath } from '../build-derivation-path/build-derivation-path';\n\nexport const deriveAddress = async (\n params: DeriveAddressParams & { approvalController: ApprovalController },\n): Promise<DeriveAddressResponse> => {\n const { approvalController, secretId } = params;\n\n // When dealing with single-account private keys, we don't need the derivation path any more.\n const derivationPath = hasDerivationDetails(params) ? buildDerivationPath(params).SVM : undefined;\n const publicKeyHex = await approvalController.requestPublicKey({\n curve: 'ed25519',\n secretId,\n derivationPath,\n });\n\n return {\n [NetworkVMType.SVM]: base58.encode(hex.decode(publicKeyHex)),\n };\n};\n","import type { DeriveAddressParams, DetailedDeriveAddressParams } from '@avalabs/vm-module-types';\n\nexport const hasDerivationDetails = (params: DeriveAddressParams): params is DetailedDeriveAddressParams =>\n 'derivationPathType' in params &&\n 'accountIndex' in params &&\n typeof params.accountIndex === 'number' &&\n typeof params.derivationPathType === 'string';\n","import {\n NetworkVMType,\n type BuildDerivationPathParams,\n type BuildDerivationPathResponse,\n} from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\n/**\n * We're deriving the BTC address from the same public key as the Ethereum address,\n * so we can determine the target address when using the Avalanche Bridge.\n */\nexport const buildDerivationPath = ({\n accountIndex,\n}: BuildDerivationPathParams): Pick<BuildDerivationPathResponse, NetworkVMType.SVM> => {\n if (accountIndex < 0) {\n throw rpcErrors.invalidParams('Account index must be a non-negative integer');\n }\n\n return {\n [NetworkVMType.SVM]: `m/44'/501'/${accountIndex}'/0'`,\n };\n};\n","import { type NetworkFeeParam, type NetworkFees } from '@avalabs/vm-module-types';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { SOL_DECIMALS } from '@src/constants';\n\nconst LamportsMultiplier = 1e6;\nexport const DEFAULT_PRIORITY_FEE = {\n high: 150 * LamportsMultiplier,\n medium: 75 * LamportsMultiplier,\n low: 2 * LamportsMultiplier,\n} as const;\n\ntype ValidRecentFees = [number, number, ...number[]];\n\nconst ensureEnoughData = (fees: number[]): ValidRecentFees => {\n const normalizedFees =\n fees.length === 0\n ? [DEFAULT_PRIORITY_FEE.low, DEFAULT_PRIORITY_FEE.low]\n : fees.length === 1\n ? [fees[0]!, DEFAULT_PRIORITY_FEE.low]\n : fees;\n\n return normalizedFees.slice().sort((a, b) => a - b) as ValidRecentFees;\n};\n\n/**\n * The RPC call (getRecentPrioritizationFees) returns the *lowest* priority fees (per compute unit)\n * that resulted in at least one transaction being succesfully included in the block.\n *\n * This means the request usually returns all zeroes - I've only once seen a different value,\n * for a single block out of 150 returned, and it was a 1000 MicroLamports.\n *\n * However, Phantom (the most popular Solana wallet) seems to always add at least a little bit\n * of priority fee.\n *\n * The lowest I've seen in my testing was 0.19 Lamport per compute unit, but this was an outlier.\n * I'm usually paying below 10 Lamports/cu, and sometimes as high as 150 or 300/cu -- all while\n * the RPC call returns zeroes, so it's not super reliable for determining the actual fees being paid :)\n *\n * The implementation here is by no means perfect. The way it I expect it to work is the following:\n * - with low/regular network traffic, users will be suggested to pay the default fees hardcoded below\n * (if we decide to show them at all -- Phantom does not show a widget at all)\n * - only when network congestion is super high, the RPC call will return non-zero values, and only then\n * we will suggest paying higher priority fees.\n */\nexport async function getNetworkFee(network: NetworkFeeParam, proxyApiUrl: string): Promise<NetworkFees> {\n const provider = getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl });\n\n const getFees = await provider.getRecentPrioritizationFees();\n const feesRaw = await getFees.send();\n\n const useDefaultFees = feesRaw.length === 0 || feesRaw.every((block) => block.prioritizationFee === 0n);\n\n if (useDefaultFees) {\n return {\n high: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.high),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.high),\n },\n medium: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.medium),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.medium),\n },\n low: {\n maxFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.low),\n maxPriorityFeePerGas: BigInt(DEFAULT_PRIORITY_FEE.low),\n },\n baseFee: BigInt(DEFAULT_PRIORITY_FEE.low),\n displayDecimals: SOL_DECIMALS,\n isFixedFee: false,\n };\n }\n\n const sortedFees = ensureEnoughData(feesRaw.map((block) => Number(block.prioritizationFee)));\n // We know the array is not empty and sorted, so we can safely access the first and last elements\n const minFeeInRecentBlocks = sortedFees.at(0)!;\n const maxFeeInRecentBlocks = sortedFees.at(-1)!;\n const midIndex = Math.floor(sortedFees.length / 2);\n const medianFee =\n sortedFees.length % 2 === 1\n ? (sortedFees[midIndex] as number)\n : (sortedFees[midIndex - 1]! + sortedFees[midIndex]!) / 2; // Even length: return average of middle elements\n\n // Prevent the fees from going below the default values\n // If the RPC call returned non-zero values, the network congestion is likely to be very high, so we add 5%.\n // We also prevent returning fees lower than the default, hardcoded values, as the RPC call is not very reliable.\n const presetHigh = BigInt(Math.ceil(maxFeeInRecentBlocks * 1.05));\n const presetMedium = BigInt(Math.ceil(medianFee * 1.05));\n const presetLow = BigInt(Math.ceil(minFeeInRecentBlocks * 1.05));\n\n // TODO: The shape of response here needs a general refactoring, it's not very generic.\n return {\n high: {\n maxFeePerGas: presetHigh,\n maxPriorityFeePerGas: presetHigh,\n },\n medium: {\n maxFeePerGas: presetMedium,\n maxPriorityFeePerGas: presetMedium,\n },\n low: {\n maxFeePerGas: presetLow,\n maxPriorityFeePerGas: presetLow,\n },\n baseFee: presetLow,\n displayDecimals: SOL_DECIMALS,\n isFixedFee: false,\n };\n}\n","import { getSolanaProvider, type SolanaProvider } from '@avalabs/core-wallets-sdk';\n\nimport { RPC_URL_DEVNET, RPC_URL_PROXY_API_ENDPOINT } from '../constants';\n\nexport const getProvider = ({\n isTestnet,\n proxyApiUrl,\n}: {\n isTestnet: boolean;\n proxyApiUrl: string;\n}): SolanaProvider => {\n return getSolanaProvider({\n isTestnet,\n rpcUrl: isTestnet ? RPC_URL_DEVNET : proxyApiUrl + RPC_URL_PROXY_API_ENDPOINT,\n });\n};\n","export const SOL_DECIMALS = 9;\nexport const SOLANA_COIN_ID = 501;\n\nexport const SOLANA_MAINNET_CAIP2_ID = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET_CAIP2_ID = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET_CAIP2_ID = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\nexport const RPC_URL_PROXY_API_ENDPOINT = '/proxy/nownodes/sol';\nexport const RPC_URL_DEVNET = 'https://api.devnet.solana.com';\nexport const RPC_URL_TESTNET = 'https://api.testnet.solana.com';\n\nexport const BLOCKAID_API_KEY = 'DUMMY_API_KEY'; // since we're using our own proxy and api key is handled there, we can use a dummy key here\n","import type { SPLToken } from '@avalabs/vm-module-types';\nimport { fetchAndVerify } from '@internal/utils/src/utils/fetch-and-verify';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { SPL_TOKENS_SCHEMA } from './spl-token-schema';\n\nexport async function getTokens({\n caip2Id,\n proxyApiUrl,\n}: {\n caip2Id: string;\n proxyApiUrl: string;\n}): Promise<SPLToken[]> {\n try {\n const tokens = await fetchAndVerify([`${proxyApiUrl}/solana-tokens?caip2Id=${caip2Id}`], SPL_TOKENS_SCHEMA);\n\n return tokens.map((token) => ({ ...token, type: token.contractType }));\n } catch (error) {\n console.error('getTokens() failed for', caip2Id, error);\n throw rpcErrors.internal(`Failed to fetch tokens for caip2Id \"${caip2Id}\"`);\n }\n}\n","import { TokenType } from '@avalabs/vm-module-types';\nimport { z } from 'zod';\n\nexport const SPL_TOKEN_SCHEMA = z.object({\n address: z.string(),\n name: z.string(),\n symbol: z.string(),\n contractType: z.literal(TokenType.SPL),\n caip2Id: z.string().startsWith('solana:'),\n decimals: z.number(),\n chainId: z.number().optional(),\n logoUri: z.string().optional(),\n color: z.string().optional(),\n});\n\nexport const SPL_TOKENS_SCHEMA = z.array(SPL_TOKEN_SCHEMA);\n","import {\n type GetBalancesParams,\n type TokenWithBalanceSVM,\n type TokenWithBalanceSPL,\n TokenType,\n type SimplePriceResponse,\n type Error,\n} from '@avalabs/vm-module-types';\nimport { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { VsCurrencyType } from '@avalabs/core-coingecko-sdk';\n\nimport type { TokenService } from '@internal/utils';\n\nimport { SOL_DECIMALS } from '@src/constants';\nimport { MoralisService } from '@src/utils/moralis-service';\nimport { getNetworkName } from '@src/utils/get-network-name';\n\ntype GetSolanaBalancesResponse = Record<\n string,\n Record<string, TokenWithBalanceSVM | TokenWithBalanceSPL | Error> | Error\n>;\n\nexport const getBalances = async ({\n addresses,\n proxyApiUrl,\n currency,\n network,\n tokenService,\n}: GetBalancesParams & {\n proxyApiUrl: string;\n tokenService: TokenService;\n}): Promise<GetSolanaBalancesResponse> => {\n const moralisService = new MoralisService({ proxyApiUrl });\n const coingeckoAssetId = network.pricingProviders?.coingecko.nativeTokenId ?? '';\n const coingeckoPlatformId = network.pricingProviders?.coingecko.assetPlatformId ?? '';\n const lowercaseCurrency = currency.toLowerCase();\n const solanaNetwork = getNetworkName(network);\n\n const portfolioResults = await Promise.all(\n addresses.map((address) => moralisService.getPortfolio({ address, network: solanaNetwork })),\n );\n\n const mints = new Set(\n portfolioResults.flatMap((result) => {\n if ('portfolio' in result) {\n return result.portfolio.tokens.map(({ mint }) => mint);\n }\n\n return [];\n }),\n );\n\n const tokenPrices = await (coingeckoPlatformId\n ? tokenService.getPricesByAddresses(Array.from(mints), coingeckoPlatformId, lowercaseCurrency as VsCurrencyType)\n : Promise.resolve(undefined));\n\n const nativeMarketData = await tokenService.getWatchlistDataForToken({\n tokenDetails: {\n symbol: network.networkToken.symbol,\n isNative: true,\n caip2Id: network.caipId ?? '',\n },\n currency: lowercaseCurrency as VsCurrencyType,\n });\n\n return portfolioResults.reduce((portfolioAcc, result) => {\n if ('error' in result) {\n return {\n ...portfolioAcc,\n [result.address]: {\n error: result.error,\n },\n };\n }\n\n const nativeBalanceUnit = new TokenUnit(result.portfolio.nativeBalance.lamports, SOL_DECIMALS, 'SOL');\n\n const nativeBalanceInCurrency =\n nativeMarketData.priceInCurrency !== undefined\n ? nativeBalanceUnit.mul(nativeMarketData.priceInCurrency)\n : undefined;\n\n const solanaBalance: TokenWithBalanceSVM = {\n type: TokenType.NATIVE,\n name: network.networkToken.name,\n symbol: network.networkToken.symbol,\n decimals: network.networkToken.decimals,\n balance: nativeBalanceUnit.toSubUnit(),\n balanceDisplayValue: nativeBalanceUnit.toString(),\n balanceInCurrency: nativeBalanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: nativeBalanceInCurrency?.toDisplay({ fixedDp: 2 }),\n logoUri: network.networkToken.logoUri ?? '',\n coingeckoId: coingeckoAssetId,\n ...nativeMarketData,\n };\n\n const tokenBalances = result.portfolio.tokens.reduce(\n (tokensAcc, { amountRaw, symbol, decimals, mint, name, logo }) => {\n const balanceUnit = new TokenUnit(amountRaw, decimals, symbol);\n const marketData = getMarketData(mint, lowercaseCurrency, tokenPrices);\n const balanceInCurrency =\n marketData.priceInCurrency !== undefined ? balanceUnit.mul(marketData.priceInCurrency) : undefined;\n\n const token: TokenWithBalanceSPL = {\n type: TokenType.SPL,\n address: mint,\n name,\n symbol,\n decimals,\n balance: balanceUnit.toSubUnit(),\n balanceDisplayValue: balanceUnit.toString(),\n balanceInCurrency: balanceInCurrency?.toDisplay({ fixedDp: 2, asNumber: true }),\n balanceCurrencyDisplayValue: balanceInCurrency?.toDisplay({ fixedDp: 2 }),\n logoUri: logo ?? undefined,\n reputation: null,\n ...marketData,\n };\n\n return {\n ...tokensAcc,\n [mint]: token,\n };\n },\n {} as Record<string, TokenWithBalanceSPL>,\n );\n\n return {\n ...portfolioAcc,\n [result.address]: {\n [network.networkToken.symbol]: solanaBalance,\n ...tokenBalances,\n },\n };\n }, {} as GetSolanaBalancesResponse);\n};\n\nconst getMarketData = (coinIdOrAddress: string, currency: string, prices?: SimplePriceResponse) => ({\n priceInCurrency: prices?.[coinIdOrAddress ?? '']?.[currency]?.price ?? undefined,\n marketCap: prices?.[coinIdOrAddress ?? '']?.[currency]?.marketCap ?? undefined,\n vol24: prices?.[coinIdOrAddress ?? '']?.[currency]?.vol24 ?? undefined,\n change24: prices?.[coinIdOrAddress ?? '']?.[currency]?.change24 ?? undefined,\n});\n","import { z } from 'zod';\n\nexport const PORTFOLIO_SCHEMA = z.object({\n nativeBalance: z.object({\n lamports: z.string(),\n solana: z.string(),\n }),\n nfts: z.array(\n z.object({\n associatedTokenAddress: z.string(),\n mint: z.string(),\n name: z.string(),\n symbol: z.string(),\n }),\n ),\n tokens: z.array(\n z.object({\n associatedTokenAddress: z.string(),\n mint: z.string(),\n amountRaw: z.string(),\n amount: z.string(),\n decimals: z.number(),\n name: z.string(),\n symbol: z.string(),\n logo: z.string().optional().nullable(),\n }),\n ),\n});\n\nexport type PortfolioResponse = z.infer<typeof PORTFOLIO_SCHEMA>;\n","import { fetchAndVerify } from '@internal/utils/src/utils/fetch-and-verify';\n\nimport type { SolanaNetworkName } from '@src/types';\n\nimport { PORTFOLIO_SCHEMA, type PortfolioResponse } from './moralis-schemas';\n\nexport class MoralisService {\n #baseUrl: string;\n\n constructor({ proxyApiUrl }: { proxyApiUrl: string }) {\n this.#baseUrl = `${proxyApiUrl}/proxy/moralis`;\n }\n\n async getPortfolio({\n address,\n network,\n }: {\n network: SolanaNetworkName;\n address: string;\n }): Promise<{ address: string; portfolio: PortfolioResponse } | { address: string; error: string }> {\n try {\n const url = this.#buildUrl(`/account/${network}/${address}/portfolio`);\n const portfolio = await fetchAndVerify([url], PORTFOLIO_SCHEMA);\n\n return {\n address,\n portfolio,\n };\n } catch (error) {\n console.error('getPortfolio() failed:', error);\n\n const message = error instanceof Error ? error.message : 'unknown error';\n\n return {\n address,\n error: `getPortfolio() failed: ${message}`,\n };\n }\n }\n\n #buildUrl(path: string) {\n return `${this.#baseUrl}${path}`;\n }\n}\n","import type { Network } from '@avalabs/vm-module-types';\n\nimport { SOLANA_DEVNET_CAIP2_ID, SOLANA_MAINNET_CAIP2_ID, SOLANA_TESTNET_CAIP2_ID } from '../constants';\n\nexport const getNetworkName = (network: Network) => {\n switch (network.caipId) {\n case SOLANA_MAINNET_CAIP2_ID:\n return 'mainnet';\n\n case SOLANA_DEVNET_CAIP2_ID:\n return 'devnet';\n\n case SOLANA_TESTNET_CAIP2_ID:\n return 'testnet';\n\n default:\n throw new Error('Unrecognized CAIP-2 id: ' + network.caipId);\n }\n};\n","import { TransactionType, type Network, type TransactionHistoryResponse, type TxToken } from '@avalabs/vm-module-types';\nimport { rpcErrors } from '@metamask/rpc-errors';\n\nimport { extractTokenTranfers, simplifyTokenBalance } from './extract-transfer';\nimport { getWrappedTransactions } from './get-wrapped-transactions';\nimport { getExplorerLink } from './get-explorer-link';\n\ntype SvmGetTransactionHistory = {\n network: Network;\n address: string;\n proxyApiUrl: string;\n};\n\nexport async function getTransactionHistory({\n network,\n address,\n proxyApiUrl,\n}: SvmGetTransactionHistory): Promise<TransactionHistoryResponse> {\n if (!network.caipId) {\n return Promise.reject({\n error: rpcErrors.invalidParams(`Network must have a CAIP-2 id`),\n });\n }\n\n const rawTransactions = await getWrappedTransactions({ network, address, proxyApiUrl });\n\n const transactions = rawTransactions\n .map(({ txHash, tx }) => {\n if (!tx.meta) {\n return null;\n }\n\n const {\n meta,\n transaction: { message },\n } = tx;\n\n // Typings are wrong here, .toString() fixes it without unnecessary casting\n const addresses = message.accountKeys.map((acc) => acc.toString());\n let accountIndex = addresses.indexOf(address);\n let isOurAddressInTransaction = accountIndex !== -1;\n\n // If not in accountKeys, check if we're an owner in token balances (for ATA transactions)\n if (!isOurAddressInTransaction && meta.preTokenBalances) {\n const isOwnerInTokenBalances =\n meta.preTokenBalances.some((balance) => balance.owner === address) ||\n (meta.postTokenBalances ?? []).some((balance) => balance.owner === address);\n if (isOwnerInTokenBalances) {\n isOurAddressInTransaction = true;\n // Set accountIndex to -1 to indicate we're not directly in accountKeys but are involved via token balances\n accountIndex = -1;\n }\n }\n\n // accountKeys property is sorted in Solana transactions. The signing keys\n // are always the first, and the header.numRequiredSignatures tells us how many\n // of the first keys are signers. If the lookup address is a signer, it has to be\n // one of the first N keys. For ATA transactions (accountIndex = -1), we're not a direct signer.\n const isSigner = accountIndex !== -1 && accountIndex < message.header.numRequiredSignatures;\n\n const transfers = extractTokenTranfers(\n addresses,\n accountIndex,\n {\n paidFee: isSigner ? Number(meta.fee) : 0,\n preBalances: meta.preBalances.map(Number),\n postBalances: meta.postBalances.map(Number),\n preTokenBalances: (meta.preTokenBalances ?? []).map(simplifyTokenBalance),\n postTokenBalances: (meta.postTokenBalances ?? []).map(simplifyTokenBalance),\n },\n network,\n );\n\n const txType = inferTxType(transfers, address);\n\n return {\n hash: txHash,\n // We should probably be smarter about the tx type, but this should be enough for MVP\n txType,\n gasUsed: String(tx.meta.computeUnitsConsumed ?? '0'),\n tokens: transfers,\n\n // Get to/from addresses from the token transfers if possible.\n // If not possible:\n // - default \"from\" to the signing address\n // - default \"to\" to our address if we're not the signer and leave empty if we don't know.\n from: transfers[0]?.from?.address ?? (addresses[0] as string),\n to: transfers[0]?.to?.address ?? (isSigner ? '' : address),\n isOutgoing: isSigner,\n isIncoming: !isSigner,\n isSender: isSigner,\n timestamp: Number(tx.blockTime) * 1000,\n isContractCall: false,\n gasPrice: String(Number(tx.meta.fee) / Number(tx.meta.computeUnitsConsumed)),\n chainId: String(network.chainId),\n explorerLink: getExplorerLink(txHash, network.explorerUrl),\n };\n })\n .filter(<T>(tx: T): tx is NonNullable<T> => tx !== null);\n\n return {\n transactions,\n };\n}\n\nconst inferTxType = (transfers: TxToken[], address: string) => {\n // No transfers = unknown\n if (transfers.length === 0) {\n return TransactionType.UNKNOWN;\n }\n\n // Check if we're the sender or receiver for each token transfer\n const ourTransfers = transfers.filter((t) => t.from?.address === address || t.to?.address === address);\n\n // If we have no transfers involving our address, it's unknown\n if (ourTransfers.length === 0) {\n return TransactionType.UNKNOWN;\n }\n\n // Check if we have both sending and receiving transfers\n const hasSending = ourTransfers.some((t) => t.from?.address === address);\n const hasReceiving = ourTransfers.some((t) => t.to?.address === address);\n\n // If we're both sending and receiving, it's a swap\n if (hasSending && hasReceiving) {\n return TransactionType.SWAP;\n }\n\n // If we're only sending\n if (hasSending) {\n return TransactionType.SEND;\n }\n\n // If we're only receiving\n if (hasReceiving) {\n return TransactionType.RECEIVE;\n }\n\n return TransactionType.UNKNOWN;\n};\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport { TokenType, type Network, type SPLToken, type TxToken } from '@avalabs/vm-module-types';\nimport type { TokenBalance } from '@solana/kit';\n\nexport const simplifyTokenBalance = (balance: TokenBalance): SimpleTokenBalance => ({\n mint: balance.mint as string,\n owner: balance.owner as string,\n amount: BigInt(balance.uiTokenAmount.amount),\n decimals: balance.uiTokenAmount.decimals,\n});\n\nexport const extractTokenTranfers: ExtractTransferFn<'SPL'> = (addresses, accountIndex, meta, network): TxToken[] => {\n // For ATA transactions (accountIndex = -1), find our address from token balances\n const ourAddress =\n accountIndex !== -1\n ? addresses[accountIndex]\n : meta.preTokenBalances.find((balance) => !addresses.includes(balance.owner))?.owner ||\n meta.postTokenBalances.find((balance) => !addresses.includes(balance.owner))?.owner;\n\n // Create a map of initial balances\n const preBalances: Record<string, bigint> = meta.preTokenBalances.reduce(\n (acc, { owner, mint, amount }) => ({\n ...acc,\n [`${owner}-${mint}`]: amount,\n }),\n {},\n );\n\n // Compare with post balances to determine transfers\n const transfers = meta.postTokenBalances.reduce((acc, { owner, mint, amount, decimals }) => {\n const key = `${owner}-${mint}`;\n const preAmount = preBalances[key] ?? 0n;\n const netChange = amount - preAmount;\n\n // Skip if no balance change\n if (netChange === 0n) {\n return acc;\n }\n\n // Determine if this is a receive or send based on balance change\n const isReceive = netChange > 0n && owner === ourAddress;\n const isSend = netChange < 0n && owner === ourAddress;\n\n if (isReceive) {\n // For receives, we need to find who sent it\n\n // For receives, find the sender by looking for addresses that had the token before but not after (or decreased)\n const sender = Object.keys(preBalances).find((k) => {\n const [possibleSender, mintFromPreBalance] = k.split('-');\n\n // Skip if it's not the same mint\n if (mintFromPreBalance !== mint) return false;\n\n // Skip if it's our address\n if (possibleSender === ourAddress) return false;\n\n // Check if this address had a balance before but not after (or decreased)\n const preBalance = preBalances[k]!;\n const postBalance = meta.postTokenBalances.find(\n ({ owner, mint: postMint }) => owner === possibleSender && postMint === mint,\n );\n\n // If no post balance, or balance decreased, this is likely the sender\n const isSender = !postBalance || postBalance.amount < preBalance;\n\n return isSender;\n });\n\n if (!sender) {\n return acc;\n }\n\n const token =\n network.tokens?.filter((t): t is SPLToken => 'contractType' in t).find((t) => t.address === mint) ??\n ({\n contractType: TokenType.SPL,\n decimals,\n address: mint,\n symbol: 'Unknown',\n name: 'Unknown',\n } as SPLToken);\n\n const transfer: TxToken = {\n ...token,\n type: token.contractType,\n from: {\n ...token,\n address: sender.split('-')[0]!,\n },\n to: {\n ...token,\n address: owner,\n },\n amount: new TokenUnit(netChange, decimals, '').toDisplay(),\n };\n\n return [...acc, transfer];\n } else if (isSend) {\n // For sends, we need to find who received it\n\n const recipient = meta.postTokenBalances.find(\n ({ owner: postBalanceOwner, mint: postBalanceMint }) =>\n postBalanceMint === mint &&\n postBalanceOwner !== ourAddress &&\n (preBalances[`${postBalanceOwner}-${mint}`] ?? 0n) <\n (meta.postTokenBalances.find((p) => p.owner === postBalanceOwner && p.mint === mint)?.amount ?? 0n),\n );\n\n if (!recipient) {\n return acc;\n }\n\n const token =\n network.tokens?.filter((t): t is SPLToken => 'contractType' in t).find((t) => t.address === mint) ??\n ({\n contractType: TokenType.SPL,\n decimals,\n address: mint,\n symbol: 'Unknown',\n name: 'Unknown',\n } as SPLToken);\n\n const transfer: TxToken = {\n ...token,\n type: token.contractType,\n from: {\n ...token,\n address: ourAddress!,\n },\n to: {\n ...token,\n address: recipient.owner,\n },\n amount: new TokenUnit(-netChange, decimals, '').toDisplay(), // Make positive for display\n };\n\n return [...acc, transfer];\n }\n\n // Skip if not our transaction\n return acc;\n }, [] as TxToken[]);\n\n const nativeTransfer = extractNativeTransfer(addresses, accountIndex, meta, network, transfers, ourAddress);\n\n if (nativeTransfer) {\n transfers.push(nativeTransfer);\n }\n\n return transfers;\n};\n\nconst extractNativeTransfer = (\n addresses: string[],\n accountIndex: number,\n { paidFee, preBalances, postBalances }: { paidFee: number; preBalances: number[]; postBalances: number[] },\n network: Network,\n splTransfers: TxToken[] = [],\n ourAddress?: string,\n): TxToken | null => {\n // For ATA transactions (accountIndex = -1), check if this might be a SOL → SPL swap\n if (accountIndex === -1) {\n // Only create SOL transfers for ATA transactions if:\n // 1. We have SPL transfers (swap context)\n // 2. We received SPL tokens (indicating we might have spent SOL)\n // 3. There's significant SOL movement in the transaction\n if (splTransfers.length > 0 && ourAddress) {\n const receivedSPL = splTransfers.some((transfer) => transfer.to?.address === ourAddress);\n\n if (receivedSPL) {\n // Find our address in the addresses array to get balance changes\n const ourAccountIndex = addresses.findIndex((addr) => addr === ourAddress);\n\n if (ourAccountIndex !== -1) {\n // We found our address - check if we spent SOL\n const nativeBalancePre = preBalances[ourAccountIndex]!;\n const nativeBalancePost = postBalances[ourAccountIndex]!;\n const rawBalanceChange = nativeBalancePost - nativeBalancePre;\n\n // If we spent SOL (including fees), create a SOL transfer for the swap\n if (rawBalanceChange <= 0) {\n const solSpent = Math.abs(rawBalanceChange) + paidFee;\n\n // Only create transfer if we spent a meaningful amount\n if (solSpent > paidFee) {\n const unit = new TokenUnit(solSpent, network.networkToken.decimals, '');\n\n // Find who received the most SOL (likely the program/pool)\n const balanceDiffs = postBalances.map((b, i) => b - preBalances[i]!);\n const largestSOLRecipient = balanceDiffs.reduce(\n (max, diff, i) => {\n if (i !== ourAccountIndex && diff > max.amount && diff > 0) {\n return { index: i, amount: diff };\n }\n return max;\n },\n { index: 0, amount: 0 },\n );\n\n return {\n amount: unit.toDisplay(),\n from: {\n address: ourAddress,\n },\n to: {\n address: addresses[largestSOLRecipient.index]!,\n },\n name: network.networkToken.name,\n symbol: network.networkToken.symbol,\n type: TokenType.NATIVE,\n };\n }\n }\n }\n }\n }\n\n return null;\n }\n\n const address = addresses[accountIndex]!;\n const nativeBalancePre = preBalances[accountIndex]!;\n const nativeBalancePost = postBalances[accountIndex]!;\n const rawBalanceChange = nativeBalancePost - nativeBalancePre;\n const balanceDiffs = postBalances.map((b, i) => b - preBalances[i]!);\n\n // Detect if we're in a swap context (SPL transfers present)\n const isSwapContext = splTransfers.length > 0;\n\n let nativeTransferAmount = rawBalanceChange !== 0 ? rawBalanceChange + paidFee : 0;\n let isIncoming = nativeTransferAmount > 0;\n let counterpartyIndex = 0;\n\n // Special case: For SOL → SPL swaps, we need to flip the SOL transfer direction\n // This happens when accountIndex=0 creates an incoming SOL transfer, but we actually spent SOL\n let isSOLtoSPLSwap = false;\n if (isSwapContext && accountIndex === 0 && ourAddress) {\n const receivedSPL = splTransfers.some((transfer) => transfer.to?.address === ourAddress);\n const sentSPL = splTransfers.some((transfer) => transfer.from?.address === ourAddress);\n\n // If we received SPL tokens but didn't send any, this is likely a SOL → SPL swap\n // The SOL transfer should be outgoing (we spent SOL to get SPL)\n if (receivedSPL && !sentSPL) {\n isIncoming = false; // Change from incoming to outgoing\n isSOLtoSPLSwap = true; // Flag to prevent override later\n // Find who received the most SOL (likely the program/pool)\n const balanceDiffs = postBalances.map((b, i) => b - preBalances[i]!);\n const largestSOLRecipient = balanceDiffs.reduce(\n (max, diff, i) => {\n if (i !== accountIndex && diff > max.amount && diff > 0) {\n return { index: i, amount: diff };\n }\n return max;\n },\n { index: 0, amount: 0 },\n );\n counterpartyIndex = largestSOLRecipient.index;\n }\n }\n\n if (isSwapContext && rawBalanceChange < 0) {\n // In a swap, if our balance decreased, look for who gained the most SOL\n // This person likely sent us SOL in the swap\n const largestGainer = balanceDiffs.reduce(\n (max, diff, i) => {\n if (i !== accountIndex && diff > max.amount) {\n return { index: i, amount: diff };\n }\n return max;\n },\n { index: 0, amount: 0 },\n );\n\n // If someone gained significant SOL (more than just fees), we likely received SOL from them\n // BUT don't override if we already detected a SOL → SPL swap\n if (largestGainer.amount > paidFee * 2 && !isSOLtoSPLSwap) {\n nativeTransferAmount = largestGainer.amount;\n isIncoming = true;\n counterpartyIndex = largestGainer.index;\n }\n } else if (isSwapContext && rawBalanceChange <= 0) {\n // Handle SOL → SPL swaps where we spent SOL to get SPL tokens\n // Check if we received SPL tokens (indicating a swap, not just a send)\n const receivedSPL = splTransfers.some((transfer) => transfer.to?.address === address);\n\n if (receivedSPL) {\n // We spent SOL to get SPL tokens - this is a swap\n // Show the SOL we spent (including fees for the total cost)\n nativeTransferAmount = Math.abs(rawBalanceChange) + paidFee;\n isIncoming = false;\n\n // Find who received the most SOL (likely the program/pool)\n const largestSOLRecipient = balanceDiffs.reduce(\n (max, diff, i) => {\n if (i !== accountIndex && diff > max.amount && diff > 0) {\n return { index: i, amount: diff };\n }\n return max;\n },\n { index: 0, amount: 0 },\n );\n\n counterpartyIndex = largestSOLRecipient.index;\n }\n }\n\n if (!nativeTransferAmount) {\n return null;\n }\n\n const unit = new TokenUnit(Math.abs(nativeTransferAmount), network.networkToken.decimals, '');\n\n // For non-swap context, use the original logic\n if (!isSwapContext) {\n const largestBeneficiary = balanceDiffs.reduce(\n ({ index, change }, netChange, i) => {\n if (netChange > change) {\n return { index: i, change: netChange };\n }\n return { index, change };\n },\n { index: 0, change: balanceDiffs[0]! },\n );\n counterpartyIndex = isIncoming ? 0 : largestBeneficiary.index;\n }\n\n // For SOL → SPL swaps, use ourAddress instead of addresses[accountIndex]\n // Handle case where counterpartyIndex is out of bounds\n const counterpartyAddress = addresses[counterpartyIndex];\n const fromAddress = isIncoming ? counterpartyAddress || address : ourAddress || address;\n const toAddress = isIncoming ? ourAddress || address : counterpartyAddress || ourAddress || address;\n\n return {\n amount: unit.toDisplay(),\n from: {\n address: fromAddress,\n },\n to: {\n address: toAddress,\n },\n name: network.networkToken.name,\n symbol: network.networkToken.symbol,\n type: TokenType.NATIVE,\n };\n};\n\ntype SimpleTokenBalance = {\n mint: string;\n owner: string;\n amount: bigint;\n decimals: number;\n};\n\ntype TxMeta = {\n paidFee: number;\n // Native SOL balances\n preBalances: number[];\n postBalances: number[];\n // SPL tokens balances\n preTokenBalances: SimpleTokenBalance[];\n postTokenBalances: SimpleTokenBalance[];\n};\n\ntype ExtractTransferFn<Type extends 'native' | 'SPL'> = (\n addresses: string[],\n accountIndex: number,\n meta: TxMeta,\n network: Network,\n) => Type extends 'native' ? TxToken | null : TxToken[];\n","import { address as solAddress, type GetTransactionApi } from '@solana/kit';\nimport type { Network } from '@avalabs/vm-module-types';\n\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { hasPropertyDefined } from '@src/utils/has-property-defined';\nimport { MoralisService } from '@src/utils/moralis-service';\nimport { getNetworkName } from '@src/utils/get-network-name';\n\ntype ParsedTx = ReturnType<GetTransactionApi['getTransaction']>;\ntype WrappedTransaction = { txHash: string; tx: NonNullable<ParsedTx> };\n\nexport const getWrappedTransactions = async ({\n network,\n address,\n proxyApiUrl,\n}: {\n network: Network;\n address: string;\n proxyApiUrl: string;\n}): Promise<WrappedTransaction[]> => {\n const provider = getProvider({ isTestnet: Boolean(network.isTestnet), proxyApiUrl });\n\n // Get main wallet signatures\n const mainSignaturesResponse = await provider.getSignaturesForAddress(solAddress(address), { limit: 25 }).send();\n const mainSignatures = mainSignaturesResponse.map((sig) => sig.signature);\n\n // Get Associated Token Account addresses from portfolio (simpler, no additional RPC calls)\n let allSignatures = mainSignatures;\n try {\n const moralisService = new MoralisService({ proxyApiUrl });\n const networkName = getNetworkName(network);\n const portfolioResult = await moralisService.getPortfolio({ address, network: networkName });\n\n if ('portfolio' in portfolioResult) {\n // Extract ATA addresses from portfolio tokens and NFTs\n const tokenATAs = portfolioResult.portfolio.tokens.map((token) => token.associatedTokenAddress);\n const nftATAs = portfolioResult.portfolio.nfts.map((nft) => nft.associatedTokenAddress);\n const ataAddresses = [...tokenATAs, ...nftATAs];\n\n // Get signatures for all ATA addresses\n const ataSignaturePromises = ataAddresses.map(async (ataAddress) => {\n try {\n const signaturesResponse = await provider\n .getSignaturesForAddress(solAddress(ataAddress), { limit: 25 })\n .send();\n return signaturesResponse.map((sig) => sig.signature);\n } catch (error) {\n console.error('Failed to get signatures for ATA:', ataAddress, error);\n return [];\n }\n });\n\n const ataSignatureResults = await Promise.allSettled(ataSignaturePromises);\n const ataSignatures = ataSignatureResults\n .filter(isFulfilled)\n .map((result) => result.value)\n .flat();\n\n // Combine and deduplicate all signatures\n allSignatures = Array.from(new Set([...mainSignatures, ...ataSignatures]));\n }\n } catch (error) {\n console.error('ATA discovery failed with error:', error);\n }\n\n // Fetch transaction data for all signatures\n const txsRequests = await Promise.allSettled(\n allSignatures.map(async (sig) => ({\n txHash: sig.toString(),\n tx: await provider.getTransaction(sig, { encoding: 'json', maxSupportedTransactionVersion: 0 }).send(),\n })),\n );\n\n return txsRequests\n .filter(isFulfilled)\n .map((tx) => tx.value)\n .filter(hasPropertyDefined('tx'));\n};\n","export const isFulfilled = <T>(result: PromiseSettledResult<T>): result is PromiseFulfilledResult<T> =>\n result.status === 'fulfilled';\n","export function hasPropertyDefined<T, K extends keyof T>(key: K) {\n return (thing: T): thing is T & Record<K, NonNullable<unknown>> => Boolean(thing[key]);\n}\n","export const getExplorerLink = (txHash: string, baseUrl?: string) => {\n const explorerLink = baseUrl ? new URL(baseUrl) : null;\n\n // Keep the query params in-tact: the Solana explorers like SolScan.io or explorer.solana.com\n // switch between clusters based on the `cluster` query param, not the domain.\n if (explorerLink) {\n explorerLink.pathname = `/tx/${txHash}`;\n }\n\n return explorerLink?.toString() ?? '';\n};\n","import { rpcErrors } from '@metamask/rpc-errors';\nimport {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Network,\n type RpcRequest,\n type SigningData,\n type SigningResult,\n} from '@avalabs/vm-module-types';\nimport { type Base64EncodedWireTransaction } from '@solana/kit';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { getNetworkName } from '@src/utils/get-network-name';\nimport { explainTransaction } from '@src/utils/explain/explain-transaction';\nimport { waitForTransactionConfirmation } from '@src/utils/wait-for-transaction-confirmation';\n\nimport { parseRequestParams, type SendOptions } from './schema';\nimport type Blockaid from '@blockaid/client';\n\nexport const signAndSendTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n blockaid,\n}: {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n blockaid: Blockaid;\n}) => {\n const { params } = request;\n const { data, success, error } = parseRequestParams(params);\n\n if (!success) {\n console.error('invalid params', error);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: error } }),\n };\n }\n\n const [{ account, serializedTx, sendOptions }] = data;\n\n const provider = getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { details, isSimulationSuccessful, alert, balanceChange } = await explainTransaction({\n simulationParams: {\n dAppUrl: request.dappInfo.url,\n params: {\n account,\n chain: getNetworkName(network),\n transactionBase64: serializedTx,\n },\n blockaid,\n },\n network,\n provider,\n });\n\n const displayData: DisplayData = {\n title: 'Do you approve this transaction?',\n network: {\n chainId: network.chainId,\n name: network.chainName,\n logoUri: network.logoUri,\n },\n details,\n alert,\n balanceChange,\n networkFeeSelector: false,\n isSimulationSuccessful,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.SOLANA_SIGN_AND_SEND_TRANSACTION,\n account,\n data: serializedTx,\n };\n\n const response = await approvalController.requestApproval({ request, displayData, signingData });\n\n if ('error' in response) {\n return {\n error: response.error,\n };\n }\n\n let txHash;\n\n try {\n txHash = await getTxHash(provider, response, sendOptions);\n await approvalController.onTransactionPending({ txHash, request });\n\n waitForTransactionConfirmation({\n provider,\n txHash,\n approvalController,\n request,\n network,\n commitment: sendOptions?.preflightCommitment,\n });\n\n return {\n result: txHash,\n };\n } catch (error) {\n console.error(error);\n // Note: we don't need to call onTransactionReverted here as waitForTransactionConfirmation handles that\n return {\n error: rpcErrors.internal({ message: 'Transaction failed', data: { cause: error } }),\n };\n }\n};\n\nconst getTxHash = async (\n provider: ReturnType<typeof getProvider>,\n response: SigningResult,\n sendOptions?: SendOptions,\n) => {\n if ('txHash' in response) {\n return response.txHash;\n }\n\n const base58TxHash = await provider\n .sendTransaction(response.signedData as Base64EncodedWireTransaction, {\n ...sendOptions,\n encoding: 'base64',\n })\n .send();\n\n return base58TxHash;\n};\n","import {\n AlertType,\n type Alert,\n type BalanceChange,\n type DetailSection,\n type Network,\n type TransactionSimulationResult,\n} from '@avalabs/vm-module-types';\n\nimport type { getProvider } from '../get-provider';\nimport { getAlertForError, transactionAlerts } from '../transaction-alerts';\n\nimport type { ExplainTxParams } from './types';\nimport { parseTransaction } from './parse-transaction';\nimport { processBalanceChange } from './blockaid/process-balance-change';\nimport { scanSolanaTransaction } from './blockaid/scan-solana-transaction';\nimport { addressItem, dataItem } from '@internal/utils';\nimport { addressListItem } from '@internal/utils/src/utils/detail-item';\n\nexport const explainTransaction = async ({\n simulationParams,\n network,\n provider,\n}: {\n simulationParams: ExplainTxParams;\n network: Network;\n provider: ReturnType<typeof getProvider>;\n}): Promise<TransactionSimulationResult & { details: DetailSection[] }> => {\n const { params } = simulationParams;\n const scanResponse = await scanSolanaTransaction(simulationParams);\n const { simulation, validation } = scanResponse?.result ?? {};\n const genericDetails: DetailSection = {\n title: 'Transaction Details',\n items: [dataItem('Raw Data', simulationParams.params.transactionBase64)],\n };\n const details: DetailSection[] = [genericDetails];\n\n let isSimulationSuccessful = false;\n let balanceChange: BalanceChange | undefined;\n let alert: Alert | undefined;\n\n if (!validation || validation.result_type === 'Warning') {\n alert = transactionAlerts[AlertType.WARNING];\n } else if (validation.result_type === 'Malicious') {\n alert = transactionAlerts[AlertType.DANGER];\n } else if (scanResponse?.error_details) {\n alert = getAlertForError(scanResponse.error_details);\n }\n\n if (simulation) {\n const { balanceChange: processedBalanceChange, otherAffectedAddresses } = processBalanceChange(\n params.account,\n simulation,\n network,\n );\n balanceChange = processedBalanceChange;\n if (otherAffectedAddresses.length > 0) {\n // Check if this is a swap (multiple tokens involved)\n const accountAssetsDiff = simulation.account_summary.account_assets_diff;\n const outgoingAssets = accountAssetsDiff?.filter((asset) => asset.out && asset.out.raw_value > 0) ?? [];\n const incomingAssets = accountAssetsDiff?.filter((asset) => asset.in && asset.in.raw_value > 0) ?? [];\n\n // Swaps: multiple assets changing hands (both outgoing and incoming)\n const isSwap = outgoingAssets.length > 0 && incomingAssets.length > 0;\n\n // For swaps, always show \"Interacting with\" regardless of address count\n // For transfers, use the existing logic\n if (isSwap) {\n genericDetails.items.push(addressItem('Account', params.account));\n genericDetails.items.push(addressListItem('Interacting with', otherAffectedAddresses));\n } else {\n // Original logic for transfers\n genericDetails.items.push(\n addressItem(otherAffectedAddresses.length === 1 ? 'From' : 'Account', params.account),\n );\n genericDetails.items.push(\n otherAffectedAddresses.length === 1\n ? addressItem('To', otherAffectedAddresses[0]!)\n : addressListItem('Interacting with', otherAffectedAddresses), // handle contract transfers\n );\n }\n } else {\n // Make sure to always show the user's address in the details.\n genericDetails.items.push(addressItem('Account', params.account));\n }\n\n isSimulationSuccessful = true;\n } else {\n // If Blockaid simulation fails, we fall back to parsing the transaction manually.\n const { balanceChange: parsedBalanceChange, details: parsedDetails } = await parseTransaction(\n params.transactionBase64,\n params.account,\n network,\n provider,\n );\n balanceChange = parsedBalanceChange;\n details.push(...parsedDetails);\n }\n\n return {\n isSimulationSuccessful,\n details,\n alert,\n balanceChange,\n };\n};\n","import { AlertType, type Alert } from '@avalabs/vm-module-types';\nimport type { MessageScanResponse } from '@blockaid/client/resources/solana/message';\n\nexport const getAlertForError = (error: MessageScanResponse['error_details']): Alert => {\n if (error?.type === 'InstructionError') {\n switch (error.code) {\n case 'ResultWithNegativeLamports':\n return {\n type: AlertType.WARNING,\n details: {\n title: 'This transaction will likely be reverted',\n description: 'Your account does not have enough SOL to perform the operation',\n },\n };\n }\n }\n\n return {\n type: AlertType.WARNING,\n details: {\n title: 'Transaction simulation has failed',\n description: 'It is possible that this transaction will fail. Please proceed with caution.',\n },\n };\n};\n\nexport const transactionAlerts = {\n [AlertType.WARNING]: {\n type: AlertType.WARNING,\n details: {\n title: 'Suspicious transaction',\n description: 'Use caution, this transaction might be malicious.',\n },\n },\n [AlertType.DANGER]: {\n type: AlertType.DANGER,\n details: {\n title: 'Scam transaction',\n description: 'This transaction is malicious, do not proceed.',\n body: ['This transaction is malicious', 'do not proceed'],\n actionTitles: {\n reject: 'Reject Transaction',\n proceed: 'Proceed Anyway',\n },\n },\n },\n};\n","import type { BalanceChange, Network, SPLToken } from '@avalabs/vm-module-types';\nimport { deserializeTransactionMessage } from '@avalabs/core-wallets-sdk';\n\nimport { isFulfilled } from '@internal/utils/src/utils/is-promise-fulfilled';\n\nimport { isNotNullish } from '../functional';\nimport type { getProvider } from '../get-provider';\nimport { tryToParseSolTransfer } from './instruction-parsers/sol-transfer';\nimport { tryToParseSPLTransfer } from './instruction-parsers/spl-transfer';\n\nexport const parseTransaction = async (\n serializedTx: string,\n account: string,\n network: Network,\n provider: ReturnType<typeof getProvider>,\n) => {\n const transaction = await deserializeTransactionMessage(serializedTx, provider);\n const balanceChange: BalanceChange = {\n ins: [],\n outs: [],\n };\n\n const details = await Promise.allSettled(\n transaction.instructions.map(async (instruction) => {\n return (\n tryToParseSolTransfer(instruction, balanceChange, account, network.networkToken) ??\n (await tryToParseSPLTransfer(provider, instruction, balanceChange, account, network.tokens as SPLToken[])) ??\n null\n );\n }),\n ).then((results) =>\n results\n .filter(isFulfilled)\n .map((result) => result.value)\n .filter(isNotNullish),\n );\n\n return {\n balanceChange,\n details,\n };\n};\n","import type { BalanceChange } from '@avalabs/vm-module-types';\n\nexport function isBalanceChangeEmpty(input: BalanceChange): boolean {\n return input.ins.length === 0 && input.outs.length === 0;\n}\n\nexport function isNotNullish<I>(input: I): input is NonNullable<I> {\n return input !== null && input !== undefined;\n}\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { BalanceChange, DetailSection, NetworkToken } from '@avalabs/vm-module-types';\nimport {\n identifySystemInstruction,\n parseTransferSolInstruction,\n SYSTEM_PROGRAM_ADDRESS,\n SystemInstruction,\n} from '@solana-program/system';\nimport {\n isInstructionForProgram,\n isInstructionWithAccounts,\n isInstructionWithData,\n type IInstruction,\n} from '@solana/kit';\n\nimport { addressItem } from '@internal/utils';\n\nexport const tryToParseSolTransfer = (\n instruction: IInstruction,\n balanceChange: BalanceChange,\n account: string,\n networkToken: NetworkToken,\n): DetailSection | null => {\n if (\n !isInstructionForProgram(instruction, SYSTEM_PROGRAM_ADDRESS) ||\n !isInstructionWithAccounts(instruction) ||\n !isInstructionWithData(instruction)\n ) {\n return null;\n }\n\n try {\n const systemInstruction = identifySystemInstruction(instruction);\n\n if (systemInstruction !== SystemInstruction.TransferSol) {\n return null;\n }\n\n const { accounts, data } = parseTransferSolInstruction({\n ...instruction,\n data: Uint8Array.from(instruction.data), // Fixing the typings here to satisfy parseTransferSolInstruction()\n });\n\n const isOutgoing = accounts.source.address === account;\n const balanceChangeKey = isOutgoing === true ? 'outs' : 'ins';\n\n balanceChange[balanceChangeKey].push({\n token: {\n ...networkToken,\n address: '',\n },\n items: [\n {\n displayValue: new TokenUnit(data.amount, networkToken.decimals, '').toString(),\n usdPrice: undefined,\n },\n ],\n });\n\n return {\n title: 'Transfer SOL',\n items: [addressItem('From', accounts.source.address), addressItem('To', accounts.destination.address)],\n };\n } catch {\n return null;\n }\n};\n","import { TokenUnit } from '@avalabs/core-utils-sdk';\nimport type { SolanaProvider } from '@avalabs/core-wallets-sdk';\nimport type { BalanceChange, DetailSection, SPLToken } from '@avalabs/vm-module-types';\nimport {\n parseTransferInstruction,\n identifyTokenInstruction,\n TokenInstruction,\n parseTransferCheckedInstruction,\n} from '@solana-program/token';\nimport { isInstructionWithAccounts, isInstructionWithData, type Address, type IInstruction } from '@solana/kit';\n\nimport { addressItem } from '@internal/utils';\n\nconst getTokenMintFromAccountInfo = async (provider: SolanaProvider, account: Address): Promise<string | null> => {\n try {\n const tokenAccountDetails = await provider.getAccountInfo(account, { encoding: 'jsonParsed' }).send();\n\n if (Array.isArray(tokenAccountDetails.value?.data)) {\n return null;\n }\n\n const info = tokenAccountDetails.value?.data.parsed.info as Record<string, unknown>;\n return typeof info?.mint === 'string' ? info.mint : null;\n } catch {\n return null;\n }\n};\n\nexport const tryToParseSPLTransfer = async (\n provider: SolanaProvider,\n instruction: IInstruction,\n balanceChange: BalanceChange,\n account: string,\n tokens?: SPLToken[],\n): Promise<DetailSection | null> => {\n if (!tokens?.length || !isInstructionWithAccounts(instruction) || !isInstructionWithData(instruction)) {\n return null;\n }\n\n try {\n const tokenInstruction = identifyTokenInstruction(instruction);\n\n if (tokenInstruction !== TokenInstruction.Transfer && tokenInstruction !== TokenInstruction.TransferChecked) {\n return null;\n }\n\n const parser =\n tokenInstruction === TokenInstruction.TransferChecked\n ? parseTransferCheckedInstruction\n : parseTransferInstruction;\n\n const { accounts, data } = parser({\n ...instruction,\n data: Uint8Array.from(instruction.data), // Fixing the typings here to satisfy parseTransferInstruction()\n });\n const tokenMint = await getTokenMintFromAccountInfo(provider, accounts.source.address);\n\n if (!tokenMint) {\n return null;\n }\n\n const token = tokens.find((t) => t.address.toLowerCase() === tokenMint.toLowerCase());\n\n if (!token) {\n return null;\n }\n\n const isOutgoing = accounts.source.address === account || accounts.authority.address === account;\n const balanceChangeKey = isOutgoing === true ? 'outs' : 'ins';\n const decimals = 'decimals' in data ? data.decimals : token.decimals;\n\n balanceChange[balanceChangeKey].push({\n token,\n items: [\n {\n displayValue: new TokenUnit(data.amount, decimals, '').toString(),\n usdPrice: undefined,\n },\n ],\n });\n\n return {\n title: `Transfer ${token.symbol}`,\n items: [addressItem('From', accounts.source.address), addressItem('To', accounts.destination.address)],\n };\n } catch {\n return null;\n }\n};\n","import type Blockaid from '@blockaid/client';\nimport {\n TokenType,\n type BalanceChange,\n type Network,\n type NetworkToken,\n type SPLToken,\n type TokenDiff,\n} from '@avalabs/vm-module-types';\n\n// Simplify access to Blockaid's typings\ntype SolanaSimulation = Blockaid.Solana.MessageScanResponse.Result.Simulation;\ntype AccountSummaryAssetDiff = SolanaSimulation['account_summary']['account_assets_diff'];\ntype SolanaSimulationAsset = Exclude<AccountSummaryAssetDiff, undefined>[number]['asset'];\n\nexport const processBalanceChange = (\n account: string,\n simulationResult: Blockaid.Solana.Message.MessageScanResponse.Result.Simulation,\n network: Network,\n): { balanceChange: BalanceChange; otherAffectedAddresses: string[] } => {\n const transferedAssets = simulationResult.account_summary.account_assets_diff ?? [];\n\n const inTokenDiffDict: Record<string, TokenDiff> = {};\n const outTokenDiffDict: Record<string, TokenDiff> = {};\n\n const otherAffectedAddresses: string[] = Object.keys(simulationResult.assets_diff ?? {}).filter(\n (key) => key !== account,\n );\n\n transferedAssets.forEach(({ asset, in: assetIn, out: assetOut }) => {\n const token = convertDiffAssetToToken(asset, network);\n\n if (!token) {\n return;\n }\n\n const identifier = 'address' in token ? token.address : token.symbol;\n\n if (assetIn) {\n if (!inTokenDiffDict[identifier]) {\n inTokenDiffDict[identifier] = {\n token,\n items: [],\n };\n }\n\n inTokenDiffDict[identifier].items.push({\n displayValue: String(assetIn.value),\n usdPrice: typeof assetIn.usd_price === 'number' ? String(assetIn.usd_price) : undefined,\n });\n }\n\n if (assetOut) {\n if (!outTokenDiffDict[identifier]) {\n outTokenDiffDict[identifier] = {\n token,\n items: [],\n };\n }\n outTokenDiffDict[identifier].items.push({\n displayValue: String(assetOut.value),\n usdPrice: typeof assetOut.usd_price === 'number' ? String(assetOut.usd_price) : undefined,\n });\n }\n });\n\n return {\n balanceChange: {\n ins: Object.values(inTokenDiffDict),\n outs: Object.values(outTokenDiffDict),\n },\n otherAffectedAddresses,\n };\n};\n\nconst convertNativeAssetToToken = (\n asset: Blockaid.Solana.MessageScanResponse.Result.Simulation.SolanaNativeAssetDiff.Asset,\n): NetworkToken => {\n return {\n name: asset.type,\n symbol: asset.type, // It's either SOL or ETH according to types\n decimals: asset.decimals,\n description: '',\n logoUri: asset.logo ?? undefined,\n };\n};\n\nconst convertTokenAssetToToken = (\n asset: Blockaid.Solana.MessageScanResponse.Result.Simulation.SolanaSplFungibleAssetDiff.Asset,\n network: Network,\n): SPLToken => ({\n type: TokenType.SPL,\n address: asset.address,\n caip2Id: network.caipId ?? '',\n contractType: TokenType.SPL,\n decimals: asset.decimals,\n name: asset.name,\n symbol: asset.symbol,\n logoUri: asset.logo || undefined,\n});\n\nconst convertDiffAssetToToken = (asset: SolanaSimulationAsset, network: Network): SPLToken | NetworkToken | null => {\n if (asset.type === 'TOKEN') {\n return convertTokenAssetToToken(asset, network);\n }\n\n if (asset.type === 'SOL' || asset.type === 'ETH') {\n return convertNativeAssetToToken(asset);\n }\n\n return null;\n};\n","import Blockaid from '@blockaid/client';\nimport { base58, base64 } from '@scure/base';\n\nimport type { ExplainTxParams } from '../types';\n\nexport const scanSolanaTransaction = async ({\n params,\n dAppUrl,\n blockaid,\n}: ExplainTxParams): Promise<Blockaid.Solana.Message.MessageScanResponse | null> => {\n try {\n return await blockaid.solana.message.scan({\n chain: params.chain,\n options: ['simulation', 'validation'],\n encoding: 'base64',\n metadata: {\n url: dAppUrl,\n },\n transactions: [params.transactionBase64],\n // We need to encode the account address to base64 as well\n account_address: base64.encode(base58.decode(params.account)),\n });\n } catch (err) {\n console.error('solana.message.scan() error', err);\n return null;\n }\n};\n","import type { ApprovalController, Network, RpcRequest } from '@avalabs/vm-module-types';\nimport type { getProvider } from './get-provider';\nimport { signature } from '@solana/kit';\nimport { getExplorerAddressByNetwork } from './get-explorer-address-by-network';\n\nconst POLLING_INTERVAL = 400; // Match Solana's block time\nconst MAX_RETRIES = 15; // ~6 seconds total - handle network congestion\n\nexport type WaitForTransactionConfirmationParams = {\n provider: ReturnType<typeof getProvider>;\n txHash: string;\n approvalController: ApprovalController;\n request: RpcRequest;\n network: Network;\n commitment?: 'processed' | 'confirmed' | 'finalized';\n maxRetries?: number;\n};\n\nexport const waitForTransactionConfirmation = async ({\n provider,\n txHash,\n approvalController,\n request,\n network,\n commitment = 'confirmed',\n maxRetries = MAX_RETRIES,\n}: WaitForTransactionConfirmationParams): Promise<boolean> => {\n let retries = 0;\n let lastStatus: string | null = null;\n const explorerLink = getExplorerAddressByNetwork(network, txHash, 'tx');\n\n while (retries < maxRetries) {\n try {\n const response = await provider\n .getSignatureStatuses([signature(txHash)], { searchTransactionHistory: true })\n .send();\n\n if (!response?.value?.[0]) {\n await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));\n retries++;\n continue;\n }\n\n const { confirmationStatus, err } = response.value[0];\n\n if (err) {\n console.error('[waitForTransactionConfirmation] Transaction failed:', err);\n approvalController.onTransactionReverted({ txHash, request });\n return false;\n }\n\n if (confirmationStatus && confirmationStatus !== lastStatus) {\n lastStatus = confirmationStatus;\n\n if (confirmationStatus === 'processed') {\n approvalController.onTransactionPending({ txHash, request });\n }\n\n const isConfirmed =\n (commitment === 'processed' && confirmationStatus === 'processed') ||\n (commitment === 'confirmed' && ['confirmed', 'finalized'].includes(confirmationStatus)) ||\n (commitment === 'finalized' && confirmationStatus === 'finalized');\n\n if (isConfirmed) {\n approvalController.onTransactionConfirmed({ txHash, request, explorerLink });\n return true;\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));\n retries++;\n } catch (error) {\n if (error instanceof Error && error.message.includes('Transaction failed')) {\n console.error('[waitForTransactionConfirmation] Transaction explicitly failed');\n approvalController.onTransactionReverted({ txHash, request });\n return false;\n }\n await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));\n retries++;\n }\n }\n\n // If we reach max retries but had a valid status, don't mark as reverted\n if (lastStatus === 'confirmed' || lastStatus === 'finalized') {\n approvalController.onTransactionConfirmed({ txHash, request, explorerLink });\n return true;\n }\n\n approvalController.onTransactionReverted({ txHash, request });\n return false;\n};\n","import type { Network } from '@avalabs/vm-module-types';\n\nconst fallbackExplorerUrl = 'https://explorer.solana.com';\n\nexport function getExplorerAddressByNetwork(network: Network, hash: string, hashType: 'address' | 'tx' = 'tx') {\n try {\n // Try to respect any query params set on {network.explorerUrl}\n const baseUrl = network.explorerUrl ? new URL(network.explorerUrl) : new URL(fallbackExplorerUrl);\n baseUrl.pathname += `${hashType}/${hash}`;\n return baseUrl.toString();\n } catch {\n return `${network.explorerUrl}/${hashType}/${hash}`;\n }\n}\n","import { z } from 'zod';\n\nconst transactionSchema = z.object({\n account: z.string(),\n serializedTx: z.string().base64(),\n sendOptions: z\n .object({\n preflightCommitment: z.enum(['processed', 'confirmed', 'finalized']).optional(),\n maxRetries: z.bigint().optional(),\n minContextSlot: z.bigint().optional(),\n skipPreflight: z.boolean().optional(),\n })\n .optional(),\n});\n\nconst paramsSchema = z.tuple([transactionSchema]);\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type TransactionParams = z.infer<typeof transactionSchema>;\nexport type SendOptions = z.infer<typeof transactionSchema>['sendOptions'];\n","import { rpcErrors } from '@metamask/rpc-errors';\nimport {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\n\nimport { getProvider } from '@src/utils/get-provider';\nimport { isBalanceChangeEmpty } from '@src/utils/functional';\nimport { getNetworkName } from '@src/utils/get-network-name';\nimport { explainTransaction } from '@src/utils/explain/explain-transaction';\n\nimport { parseRequestParams } from './schema';\nimport type Blockaid from '@blockaid/client';\n\nexport const signTransaction = async ({\n request,\n network,\n approvalController,\n proxyApiUrl,\n blockaid,\n}: {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n proxyApiUrl: string;\n blockaid: Blockaid;\n}) => {\n const { params } = request;\n const { data, success, error } = parseRequestParams(params);\n\n if (!success) {\n console.error('invalid params', error);\n return {\n error: rpcErrors.invalidParams({ message: 'Transaction params are invalid', data: { cause: error } }),\n };\n }\n\n const [{ account, serializedTx }] = data;\n\n const provider = getProvider({\n isTestnet: Boolean(network.isTestnet),\n proxyApiUrl,\n });\n\n const { details, isSimulationSuccessful, alert, balanceChange } = await explainTransaction({\n simulationParams: {\n dAppUrl: request.dappInfo.url,\n params: {\n account,\n chain: getNetworkName(network),\n transactionBase64: serializedTx,\n },\n blockaid,\n },\n network,\n provider,\n });\n\n const displayData: DisplayData = {\n title: 'Do you approve this transaction?',\n network: {\n chainId: network.chainId,\n name: network.chainName,\n logoUri: network.logoUri,\n },\n details,\n alert,\n balanceChange: balanceChange && isBalanceChangeEmpty(balanceChange) ? undefined : balanceChange,\n networkFeeSelector: false,\n isSimulationSuccessful,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.SOLANA_SIGN_TRANSACTION,\n account,\n data: serializedTx,\n };\n\n const response = await approvalController.requestApproval({ request, displayData, signingData });\n\n if ('error' in response) {\n return {\n error: response.error,\n };\n }\n\n if (!('signedData' in response)) {\n return {\n error: rpcErrors.invalidRequest('No signed data returned'),\n };\n }\n\n return { result: response.signedData };\n};\n","import { z } from 'zod';\n\nconst transactionSchema = z.object({\n account: z.string(),\n serializedTx: z.string().base64(),\n});\n\nconst paramsSchema = z.tuple([transactionSchema]);\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type TransactionParams = z.infer<typeof transactionSchema>;\n","import { rpcErrors } from '@metamask/rpc-errors';\nimport {\n RpcMethod,\n type ApprovalController,\n type DisplayData,\n type Network,\n type RpcRequest,\n type SigningData,\n} from '@avalabs/vm-module-types';\nimport { base64 } from '@scure/base';\n\nimport { addressItem, dataItem, textItem } from '@internal/utils';\n\nimport { parseRequestParams } from './schema';\n\nexport const signMessage = async ({\n request,\n network,\n approvalController,\n}: {\n request: RpcRequest;\n network: Network;\n approvalController: ApprovalController;\n}) => {\n const { params } = request;\n const { data, success, error } = parseRequestParams(params);\n\n if (!success) {\n console.error('invalid params', error);\n return {\n error: rpcErrors.invalidParams({ message: 'Message signing params are invalid', data: { cause: error } }),\n };\n }\n\n const [{ account, serializedMessage }] = data;\n\n const utf8Decoder = new TextDecoder();\n const displayData: DisplayData = {\n title: 'Sign Message',\n network: {\n chainId: network.chainId,\n name: network.chainName,\n logoUri: network.logoUri,\n },\n dAppInfo: {\n name: request.dappInfo.name,\n action: `${request.dappInfo.name} is requesting to sign the following message`,\n logoUri: request.dappInfo.icon,\n },\n details: [\n {\n title: 'Message Details',\n items: [\n addressItem('Account', account),\n textItem('Message', utf8Decoder.decode(base64.decode(serializedMessage))),\n dataItem('Raw Message (Base-64)', serializedMessage),\n ],\n },\n ],\n networkFeeSelector: false,\n };\n\n const signingData: SigningData = {\n type: RpcMethod.SOLANA_SIGN_MESSAGE,\n account,\n data: serializedMessage,\n };\n\n const response = await approvalController.requestApproval({ request, displayData, signingData });\n\n if ('error' in response) {\n return {\n error: response.error,\n };\n }\n\n if (!('signedData' in response)) {\n return {\n error: rpcErrors.invalidRequest('No signed data returned'),\n };\n }\n\n return { result: response.signedData };\n};\n","import { base64 } from '@scure/base';\nimport { getCompiledTransactionMessageDecoder } from '@solana/kit';\n\nexport const isTransactionBytes = (base64Payload: string): boolean => {\n try {\n const bytes = base64.decode(base64Payload);\n const decoder = getCompiledTransactionMessageDecoder();\n decoder.decode(bytes);\n return true;\n } catch {\n return false;\n }\n};\n","import { isTransactionBytes } from '@src/utils/is-transaction-bytes';\nimport { z } from 'zod';\n\nconst signMessageSchema = z\n .object({\n account: z.string(),\n serializedMessage: z.string().base64(),\n })\n .refine(({ serializedMessage }) => !isTransactionBytes(serializedMessage), {\n message: 'Cannot use signMessage() calls for signing transactions',\n });\n\nconst paramsSchema = z.tuple([signMessageSchema]);\n\nexport const parseRequestParams = (params: unknown) => {\n return paramsSchema.safeParse(params);\n};\n\nexport type SignMessageParams = z.infer<typeof signMessageSchema>;\n"]}