@parifi/synthetix-sdk-ts
Version:
A Typescript SDK for interactions with the Synthetix protocol
1 lines • 364 kB
Source Map (JSON)
{"version":3,"sources":["../src/utils/common.ts","../src/constants/partner.ts","../src/constants/protocol.ts","../src/constants/common.ts","../src/constants/pythPriceIds.ts","../src/contracts/addreses/zap.ts","../src/utils/index.ts","../src/contracts/abis/IERC7412.ts","../src/utils/parseError.ts","../src/contracts/addreses/oracleProxy.ts","../src/core/index.ts","../src/index.ts","../src/contracts/v3-contracts/42161/index.ts","../src/contracts/abis/zap.ts","../src/contracts/v3-contracts/421614/index.ts","../src/contracts/v3-contracts/8453/index.ts","../src/contracts/v3-contracts/84532/index.ts","../src/contracts/helpers.ts","../src/contracts/index.ts","../src/pyth/index.ts","../src/perps/index.ts","../src/utils/market.ts","../src/utils/override.ts","../src/constants/slots.ts","../src/spot/index.ts"],"sourcesContent":["import { Address, formatEther, maxUint128, parseEther } from 'viem';\n\nimport { mainnet, base, optimism, arbitrum, baseSepolia, arbitrumSepolia, Chain } from 'viem/chains';\nimport { randomBytes } from 'crypto';\nimport { publicRpcEndpoints } from '../constants';\nimport { ZAP_BY_CHAIN } from '../contracts/addreses/zap';\n\nexport function getPublicRpcEndpoint(chainId: number) {\n return publicRpcEndpoints[chainId];\n}\n\n/**\n * Gets the chain object for the given chain id.\n * @param chainId - Chain id of the target EVM chain.\n * @returns Viem's chain object.\n */\nexport function getChain(chainId: number): Chain {\n const chains = [mainnet, base, optimism, arbitrum, baseSepolia, arbitrumSepolia];\n for (const chain of Object.values(chains)) {\n if (chain.id === chainId) {\n return chain;\n }\n }\n throw new Error(`Chain with id ${chainId} not found`);\n}\n\nexport function convertWeiToEther(amountInWei: string | bigint | undefined): number {\n if (amountInWei == undefined) {\n throw new Error('Invalid amount received during conversion: undefined');\n }\n if (typeof amountInWei == 'bigint') {\n return Number(formatEther(amountInWei));\n } else if (typeof amountInWei == 'string') {\n return Number(formatEther(BigInt(amountInWei)));\n } else {\n throw new Error('Expected string or bigint for conversion');\n }\n}\n\nexport function convertEtherToWei(amount: string | number | undefined): bigint {\n if (amount == undefined) {\n throw new Error('Invalid amount received during conversion: undefined');\n }\n if (typeof amount == 'number') {\n return parseEther(amount.toString());\n } else if (typeof amount == 'string') {\n return parseEther(amount);\n } else {\n throw new Error('Expected string or bigint for conversion');\n }\n}\n\nexport function sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, seconds * 1000));\n}\n\nexport function generateRandomAccountId(): bigint {\n const maxUint128Half = maxUint128 / BigInt(2);\n\n const buffer = randomBytes(8); // 8 bytes * 8 bits/byte = 64 bits\n const randomAccountId = BigInt('0x' + buffer.toString('hex'));\n if (randomAccountId > maxUint128Half) {\n throw new Error('Account ID greater than Maxuint128');\n }\n return randomAccountId;\n}\n\n/**\n * @name batchArray\n * @description This function batches an array into smaller subarrays based on a given size. It uses the reduce method to iterate over the array and push each batch into an accumulator array.\n * @param {any[]} arr - The array that needs to be batched.\n * @param {number} batchSize - The number of elements to include in each subarray.\n * @returns {any[][]} - An array of arrays, where each inner array contains the batched subarrays.\n */\nexport const batchArray = <T>(arr: T[], batchSize: number): T[][] => {\n return arr.reduce((acc, _, i) => (i % batchSize ? acc : [...acc, arr.slice(i, i + batchSize)]), [] as T[][]);\n};\n\nexport type QuoteParams = {\n fromChain: number;\n fromToken: Address;\n toToken: Address;\n fromAmount: string;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type FetcherArgs = Omit<RequestInit, 'body'> & { body?: any };\n\nexport const fetcher = (\n url: string,\n init: FetcherArgs = {\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n) =>\n fetch(url, {\n ...init,\n body: JSON.stringify(init.body),\n headers: init.headers,\n method: init.body && !init.method ? 'POST' : init.method,\n });\n\nconst odoFetcher = async (url: string, options: FetcherArgs) => {\n return fetcher(`https://api.odos.xyz/sor${url}`, options);\n};\n\nconst assemblePath = async (user: string, pathId: string) => {\n const response = await odoFetcher(`/assemble`, {\n body: {\n userAddr: user,\n pathId,\n },\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) return '';\n const data = (await response.json()) as { transaction: { data: string } };\n\n return data.transaction.data;\n};\n\nexport const getOdosPath = async (quoteParams: QuoteParams) => {\n if (!quoteParams.fromToken || !quoteParams.toToken || !quoteParams.fromAmount) {\n throw new Error('Missing required parameters for Odos path generation');\n }\n\n const data = {\n chainId: quoteParams.fromChain,\n inputTokens: [{ tokenAddress: quoteParams.fromToken, amount: quoteParams.fromAmount }],\n outputTokens: [{ tokenAddress: quoteParams.toToken, proportion: 1 }],\n userAddr: ZAP_BY_CHAIN[quoteParams.fromChain],\n };\n\n const response = await odoFetcher('/quote/v2', {\n body: data,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n console.error(`Failed to get Odos quote: ${response.status} ${response.statusText}`);\n return { path: '' };\n }\n\n const quote = (await response.json()) as { pathId: string };\n if (!quote?.pathId) {\n console.error('Invalid response from Odos API: missing pathId');\n return { path: '' };\n }\n const quoteId = quote.pathId;\n\n const path = await assemblePath(data.userAddr, quoteId);\n if (!path) {\n console.error('Failed to assemble path from pathId');\n }\n\n return { path };\n};\n","export const DEFAULT_TRACKING_CODE = '0x5052460000000000000000000000000000000000000000000000000000000000';\nexport const DEFAULT_REFERRER = '0x32A74B2cE1a0783A182f607D29207e571a1cDD4D';\n","export const DEFAULT_NETWORK_ID = 8453;\n\nexport const DEFAULT_DECIMALS = 18;\nexport const DEFAULT_SLIPPAGE = 2.0;\nexport const DEFAULT_GAS_MULTIPLIER = 2.0;\n\nexport const PUBLIC_PYTH_ENDPOINT = 'https://hermes.pyth.network';\nexport const DEFAULT_PYTH_TIMEOUT = 15000; // 15 sec\n","import { Hex, zeroAddress } from 'viem';\nimport { MarketIdOrName } from '../interface/commonTypes';\nimport { SUPPORTED_CHAINS } from './chains';\n\nexport const ZERO_ADDRESS: Hex = zeroAddress;\n\nexport const SIG_ORACLE_DATA_REQUIRED = '0xcf2cabdf';\nexport const SIG_FEE_REQUIRED = '0x0e7186fb';\nexport const SIG_ERRORS = '0x0b42fd17';\n\n// for markets metadata it is requesting too much oracle updates\nexport const MAX_ERC7412_RETRIES = 80; // Limit the max failures to prevent infinite loops\n\n// List of market ids disabled by chainId\nexport const DISABLED_MARKETS: { [key: number]: number[] } = {\n 84532: [3, 6300],\n 8453: [6300],\n};\n\nexport const publicRpcEndpoints: { [key: number]: string } = {\n 8453: 'https://base.llamarpc.com',\n 84532: 'https://sepolia.base.org',\n 42161: 'https://arbitrum.llamarpc.com',\n 421614: 'https://sepolia-rollup.arbitrum.io/rpc',\n};\n\n// Logger constants\nexport type LOGGER_MESSAGE_TYPE = 'json' | 'pretty' | 'hidden';\n\n// 0: silly, 1: trace, 2: debug, 3: info, 4: warn, 5: error, 6: fatal\nexport const DEFAULT_LOGGER_LEVEL = 4; // https://tslog.js.org/#/?id=highlights to see more levels\nexport const CUSTOM_DECIMALS: Record<number, Record<MarketIdOrName, number>> = {\n [SUPPORTED_CHAINS.ARBITUM_SEPOLIA]: {\n 2: 6,\n USDC: 6,\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n 2: 6,\n USDC: 6,\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n 1: 6,\n USDC: 6,\n },\n [SUPPORTED_CHAINS.BASE]: {\n 1: 6,\n USDC: 6,\n },\n};\n","export const SYMBOL_TO_PYTH_FEED = new Map<string, string>([\n // Markets\n ['BTC', '0xc9d8b075a5c69303365ae23633d4e085199bf5c520a3b90fed1322a0342ffc33'],\n ['SOL', '0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d'],\n ['WIF', '0x4ca4beeca86f0d164160323817a4e42b10010a724c2217c6ee41b54cd4cc61fc'],\n ['ETH', '0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace'],\n ['AAVE', '0x2b9ab1e972a281585084148ba1389800799bd4be63b957507db1349314e47445'],\n ['ADA', '0x2a01deaec9e51a579277b34b122399984d0bbf57e2458a7e42fecd2829867a0d'],\n ['ARB', '0x3fa4252848f9f0a1480be62745a4629d9eb1322aebab8a791e344b3b9c1adcf5'],\n ['AVAX', '0x93da3352f9f1d105fdfe4971cfa80e9dd777bfc5d0f683ebb6e1294b92137bb7'],\n ['BCH', '0x3dd2b63686a450ec7290df3a1e0b583c0481f651351edfa7636f39aed55cf8a3'],\n ['BNB', '0x2f95862b045670cd22bee3114c39763a4a08beeb663b145d283c31d7d1101c4f'],\n ['CRV', '0xa19d04ac696c7a6616d291c7e5d1377cc8be437c327b75adb5dc1bad745fcae8'],\n ['DOGE', '0xdcef50dd0a4cd2dcc17e45df1676dcb336a11a61c69df7a0299b0150c672d25c'],\n ['DYDX', '0x6489800bb8974169adfe35937bf6736507097d13c190d760c557108c7e93a81b'],\n ['GMX', '0xb962539d0fcb272a494d65ea56f94851c2bcf8823935da05bd628916e2e9edbf'],\n ['LINK', '0x8ac0c70fff57e9aefdf5edf44b51d62c2d433653cbb2cf5cc06bb115af04d221'],\n ['LTC', '0x6e3f3fa8253588df9326580180233eb791e03b443a3ba7a1d892e73874e19a54'],\n ['MKR', '0x9375299e31c0deb9c6bc378e6329aab44cb48ec655552a70d4b9050346a30378'],\n ['NEAR', '0xc415de8d2eba7db216527dff4b60e8f3a5311c740dadb233e13e12547e226750'],\n ['OP', '0x385f64d993f7b77d8182ed5003d97c60aa3361f3cecfe711544d2d59165e9bdf'],\n ['ORDI', '0x193c739db502aadcef37c2589738b1e37bdb257d58cf1ab3c7ebc8e6df4e3ec0'],\n ['PEPE', '0xd69731a2e74ac1ce884fc3890f7ee324b6deb66147055249568869ed700882e4'],\n ['POL', '0xffd11c5a1cfd42f80afb2df4d9f264c15f956d68153335374ec10722edd70472'],\n ['PYTH', '0x0bbf28e9a841a1cc788f6a361b17ca072d0ea3098a1e5df1c3922d06719579ff'],\n ['RUNE', '0x5fcf71143bb70d41af4fa9aa1287e2efd3c5911cee59f909f915c9f61baacb1e'],\n ['SHIB', '0xf0d57deca57b3da2fe63a493f4c25925fdfd8edf834b20f93e1f84dbd1504d4a'],\n ['STX', '0xec7a775f46379b5e943c3526b1c8d54cd49749176b0b98e02dde68d1bd335c17'],\n ['TIA', '0x09f7c1d7dfbb7df2b8fe3d3d87ee94a2259d212da4f30c1f0540d066dfa44723'],\n ['UNI', '0x78d185a741d07edb3412b09008b7c5cfb9bbbd7d568bf00ba737b456ba171501'],\n ['XLM', '0xb7a8eba68a997cd0210c2e1e4ee811ad2d174b3611c22d9ebf16f4cb7e9ba850'],\n ['XRP', '0xec5d399846a9209f3fe5881d70aae9268c94339ff9817e8d18ff19fa05eea1c8'],\n ['ATOM', '0xb00b60f88b03a6a625a8d1c048c3f66653edf217439983d037e7222c4e612819'],\n ['BLUR', '0x856aac602516addee497edf6f50d39e8c95ae5fb0da1ed434a8c2ab9c3e877e9'],\n ['BOME', '0x30e4780570973e438fdb3f1b7ad22618b2fc7333b65c7853a7ca144c39052f7a'],\n ['BONK', '0x72b021217ca3fe68922a19aaf990109cb9d84e9ad004b4d2025ad6f529314419'],\n ['COMP', '0x4a8e42861cabc5ecb50996f92e7cfa2bce3fd0a2423b0c44c9b423fb2bd25478'],\n ['DOT', '0xca3eed9b267293f6595901c734c7525ce8ef49adafe8284606ceb307afa2ca5b'],\n ['EIGEN', '0xc65db025687356496e8653d0d6608eec64ce2d96e2e28c530e574f0e4f712380'],\n ['ENA', '0xb7910ba7322db020416fcac28b48c01212fd9cc8fbcbaf7d30477ed8605f6bd4'],\n ['EOS', '0x06ade621dbc31ed0fc9255caaab984a468abe84164fb2ccc76f02a4636d97e31'],\n ['ETC', '0x7f5cc8d963fc5b3d2ae41fe5685ada89fd4f14b435f8050f28c7fd409f40c2d8'],\n ['ETHBTC', '0xc96458d393fe9deb7a7d63a0ac41e2898a67a7750dbd166673279e06c868df0a'],\n ['ETHFI', '0xb27578a9654246cb0a2950842b92330e9ace141c52b63829cc72d5c45a5a595a'],\n ['FIL', '0x150ac9b959aee0051e4091f0ef5216d941f590e1c5e7f91cf7635b5c11628c0e'],\n ['FLOW', '0x2fb245b9a84554a0f15aa123cbb5f64cd263b59e9a87d80148cbffab50c69f30'],\n ['FTM', '0x5c6c0d2386e3352356c3ab84434fafb5ea067ac2678a38a338c4a69ddc4bdb0c'],\n ['FXS', '0x735f591e4fed988cd38df74d8fcedecf2fe8d9111664e0fd500db9aa78b316b1'],\n ['GALA', '0x0781209c28fda797616212b7f94d77af3a01f3e94a5d421760aef020cf2bcb51'],\n ['GRT', '0x4d1f8dae0d96236fb98e8f47471a366ec3b1732b47041781934ca3a9bb2f35e7'],\n ['ICP', '0xc9907d786c5821547777780a1e4f89484f3417cb14dd244f2b0a34ea7a554d67'],\n ['IMX', '0x941320a8989414874de5aa2fc340a75d5ed91fdff1613dd55f83844d52ea63a2'],\n ['INJ', '0x7a5bc1d2b56ad029048cd63964b3ad2776eadf812edc1a43a31406cb54bff592'],\n ['IO', '0x82595d1509b770fa52681e260af4dda9752b87316d7c048535d8ead3fa856eb1'],\n ['JTO', '0xb43660a5f790c69354b0729a5ef9d50d68f1df92107540210b9cccba1f947cc2'],\n ['JUP', '0x0a0408d619e9380abad35060f9192039ed5042fa6f82301d0e48bb52be830996'],\n ['LDO', '0xc63e2a7f37a04e5e614c07238bedb25dcc38927fba8fe890597a593c0b2fa4ad'],\n ['MEME', '0xcd2cee36951a571e035db0dfad138e6ecdb06b517cc3373cd7db5d3609b7927c'],\n ['MEW', '0x514aed52ca5294177f20187ae883cec4a018619772ddce41efcc36a6448f5d5d'],\n ['NOT', '0x75ec6f04d4bded6afdc1440689be4402dd1e23d2ff2c21e081871eb2739ceb36'],\n ['PENDLE', '0x9a4df90b25497f66b1afb012467e316e801ca3d839456db028892fe8c70c8016'],\n ['PEOPLE', '0xb7fe919d83815ca6074c82a3286b1cd6ffb7d3136e323cd2b1ef706cfc7e5945'],\n ['POPCAT', '0xb9312a7ee50e189ef045aa3c7842e099b061bd9bdc99ac645956c3b660dc8cce'],\n ['RENDER', '0x3d4a2bd9535be6ce8059d75eadeba507b043257321aa544717c56fa19b49e35d'],\n ['SATS', '0x40440d18fb5ad809e2825ce7dfc035cfa57135c13062a04addafe0c7f54425e0'],\n ['SEI', '0x53614f1cb0c031d4af66c04cb9c756234adad0e1cee85303795091499a4084eb'],\n ['SNX', '0x39d020f60982ed892abbcd4a06a276a9f9b7bfbce003204c110b6e488f502da3'],\n ['STRK', '0x6a182399ff70ccf3e06024898942028204125a819e519a335ffa4579e66cd870'],\n ['SUI', '0x23d7315113f5b1d3ba7a83604c44b94d79f4fd69af77f804fc7f920a6dc65744'],\n ['SUSHI', '0x26e4f737fde0263a9eea10ae63ac36dcedab2aaf629261a994e1eeb6ee0afe53'],\n ['TAO', '0x410f41de235f2db824e562ea7ab2d3d3d4ff048316c61d629c0b93f58584e1af'],\n ['TON', '0x8963217838ab4cf5cadc172203c1f0b763fbaa45f346d8ee50ba994bbcac3026'],\n ['TRX', '0x67aed5a24fdad045475e7195c98a98aea119c763f272d4523f5bac93a4f33c2b'],\n ['W', '0xeff7446475e218517566ea99e72a4abec2e1bd8498b43b7d8331e29dcb059389'],\n ['WLD', '0xd6835ad1f773de4a378115eb6824bd0c0e42d84d1c84d9750e853fb6b6c7794a'],\n ['YFI', '0x425f4b198ab2504936886c1e93511bb6720fbcf2045a4f3c0723bb213846022f'],\n ['ZRO', '0x3bd860bea28bf982fa06bcf358118064bb114086cc03993bd76197eaab0b8018'],\n ['ALGO', '0xfa17ceaf30d19ba51112fdcc750cc83454776f47fb0112e4af07f15f4bb1ebc0'],\n ['APT', '0x03ae4db29ed4ae33d323568895aa00337e658e348b37509f5372ae51f0af00d5'],\n ['ARKM', '0x7677dd124dee46cfcd46ff03cf405fb0ed94b1f49efbea3444aadbda939a7ad3'],\n ['AXL', '0x60144b1d5c9e9851732ad1d9760e3485ef80be39b984f6bf60f82b28a2b7f126'],\n ['AXS', '0xb7e3904c08ddd9c0c10c6d207d390fd19e87eb6aab96304f571ed94caebdefa0'],\n ['BAL', '0x07ad7b4a7662d19a6bc675f6b467172d2f3947fa653ca97555a9b20236406628'],\n ['GOAT', '0xf7731dc812590214d3eb4343bfb13d1b4cfa9b1d4e020644b5d5d8e07d60c66c'],\n ['MOODENG', '0xffff73128917a90950cd0473fd2551d7cd274fd5a6cc45641881bbcc6ee73417'],\n ['SAFE', '0x7b3576858506a94fad3a9cc55e32934f0c3931150fe3a3c7b83558dbae5b8e38'],\n ['PNUT', '0x116da895807f81f6b5c5f01b109376e7f6834dc8b51365ab7cdfa66634340e54'],\n ['CAT', '0xdf7b724fae4b9ecfd6081effb1ea3bb3b5c250c3641cf903b4d8fb10f4f452df'],\n ['DEGEN', '0x9c93e4a22c56885af427ac4277437e756e7ec403fbc892f975d497383bb33560'],\n ['SLERF', '0x1a483c4a63876d286991ac0d6e090298db42e88c3826b6e0cff89daca498eed5'],\n ['AERO', '0x9db37f4d5654aad3e37e2e14ffd8d53265fb3026d1d8f91146539eebaa2ef45f'],\n ['CHILLGUY', '0xd98869edbb4a0d2803dc1054405bceb1ddc546bfc9a3d0e31bb0e0448e6181e1'],\n ['MORPHO', '0x5b2a4c542d4a74dd11784079ef337c0403685e3114ba0d9909b5c7a7e06fdc42'],\n ['SOLETH', '0xde87506dabfadbef89af2d5d796ebae80ddaea240fc7667aa808fce3629cd8fb'],\n // Collaterals\n ['USDC', '0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a'],\n ['USDE', '0x6ec879b1e9963de5ee97e9c8710b742d6228252a5e2ca12d4ae81d7fe5ee8c5d'],\n ['DAI', '0xb0948a5e5313200c632b51bb5ca32f6de0d36e9950a942d19751e833f70dabfd'],\n]);\n","import { Address, zeroAddress } from 'viem';\nimport { SUPPORTED_CHAINS } from '../../constants/chains';\n\nexport const ZAP_BY_CHAIN: Record<number, Address> = {\n [SUPPORTED_CHAINS.BASE]: '0x459Bbb4231f0a606DC514BacD5712A5922CBe6c8',\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: zeroAddress,\n [SUPPORTED_CHAINS.ARBITRUM]: '0x9ec181B2E69fB36C50031F0c87Bc0749b766A9f4',\n [SUPPORTED_CHAINS.ARBITUM_SEPOLIA]: '0xb569ed692206a1d73996088ae646333b1d59d9c5',\n};\n\nexport const SYNTHETIX_ZAP: Record<number, Address> = {\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: '0xA6Fab50eB36F3eB2118eE2f4C12C968F8608bbc9',\n [SUPPORTED_CHAINS.BASE]: '0xA6Fab50eB36F3eB2118eE2f4C12C968F8608bbc9',\n};\n","export * from './common';\n\nimport {\n Abi,\n Address,\n CallExecutionError,\n CallParameters,\n decodeAbiParameters,\n decodeErrorResult,\n decodeFunctionResult,\n encodeAbiParameters,\n encodeFunctionData,\n Hash,\n Hex,\n parseAbiParameters,\n StateMapping,\n StateOverride,\n} from 'viem';\nimport { SynthetixSdk } from '..';\nimport { IERC7412Abi } from '../contracts/abis/IERC7412';\nimport { Call3Value, Result } from '../interface/contractTypes';\nimport { parseError } from './parseError';\nimport { MAX_ERC7412_RETRIES, SIG_ERRORS, SIG_FEE_REQUIRED, SIG_ORACLE_DATA_REQUIRED } from '../constants';\nimport {\n OverrideParamsRead,\n OverrideParamsWrite,\n TransactionData,\n WriteContractParams,\n WriteErc7412,\n WriteReturnType,\n} from '../interface/commonTypes';\nimport { batchArray } from './common';\nimport { ORACLE_PROXY_BY_CHAIN } from '../contracts/addreses/oracleProxy';\n/**\n * Utility class\n *\n */\nexport class Utils {\n sdk: SynthetixSdk;\n constructor(synthetixSdk: SynthetixSdk) {\n this.sdk = synthetixSdk;\n }\n\n public async isOracleCall(data: TransactionData | Address) {\n return Object.values(ORACLE_PROXY_BY_CHAIN)\n .map((a) => a.toLowerCase())\n .includes(typeof data === 'string' ? data.toLowerCase() : data.to.toLowerCase());\n }\n\n /**\n * Returns the Pyth price ids array\n * @param oracleQueryData\n * @returns Pyth Price IDs array\n */\n public getPythPriceIdsFromOracleQuery(oracleQueryData: Hex): Hex[] {\n const values = decodeAbiParameters(parseAbiParameters('uint8, uint64, bytes32[]'), oracleQueryData);\n return values[2] as Hex[];\n }\n\n /**\n * Decodes the response from a Smart contract function call\n * @param abi Contract ABI\n * @param functionName Function name to decode\n * @param result Response from function call that needs to be decoded\n * @returns Decoded result\n */\n public decodeResponse(abi: unknown, functionName: string, result: Hex) {\n const decodedResult = decodeFunctionResult({\n abi: abi as Abi,\n functionName: functionName,\n data: result,\n });\n\n return decodedResult;\n }\n\n /**\n * Determines the type of Error emitted by ERC7412 contract and prepares signed update data\n * @param data Error data emitted from ERC7412 contract\n * @returns Encoded data for oracle price update transaction\n */\n public async fetchOracleUpdateData(data: Hex): Promise<Hex> {\n const [updateType] = decodeAbiParameters([{ name: 'updateType', type: 'uint8' }], data);\n\n if (updateType === 1) {\n const [updateType, stalenessOrTime, priceIds] = decodeAbiParameters(\n [\n { name: 'updateType', type: 'uint8' },\n { name: 'stalenessTolerance', type: 'uint64' },\n { name: 'priceIds', type: 'bytes32[]' },\n ],\n data,\n );\n\n const stalenessTolerance = stalenessOrTime;\n const updateData = (await this.sdk.pyth.pythConnection.getPriceFeedsUpdateData(\n priceIds as string[],\n )) as unknown as Address[];\n\n return encodeAbiParameters(\n [\n { type: 'uint8', name: 'updateType' },\n { type: 'uint64', name: 'stalenessTolerance' },\n { type: 'bytes32[]', name: 'priceIds' },\n { type: 'bytes[]', name: 'updateData' },\n ],\n [updateType, stalenessTolerance, priceIds, updateData],\n );\n } else if (updateType === 2) {\n const [updateType, requestedTime, priceId] = decodeAbiParameters(\n [\n { name: 'updateType', type: 'uint8' },\n { name: 'requestedTime', type: 'uint64' },\n { name: 'priceIds', type: 'bytes32' },\n ],\n data,\n );\n this.sdk.logger.info('Update type: ', updateType);\n this.sdk.logger.info('priceIds: ', priceId);\n\n const [priceFeedUpdateVaa] = await this.sdk.pyth.pythConnection.getVaa(\n priceId as string,\n Number((requestedTime as unknown as bigint).toString()),\n );\n const priceFeedUpdate = '0x' + Buffer.from(priceFeedUpdateVaa, 'base64').toString('hex');\n\n return encodeAbiParameters(\n [\n { type: 'uint8', name: 'updateType' },\n { type: 'uint64', name: 'timestamp' },\n { type: 'bytes32[]', name: 'priceIds' },\n { type: 'bytes[]', name: 'updateData' },\n ],\n [updateType, requestedTime, [priceId], [priceFeedUpdate as Address]],\n );\n } else {\n throw new Error(`Error encoding/decoding data`);\n }\n }\n\n async handleOracleDataRequiredError(parsedError: Hash): Promise<Call3Value> {\n const err = decodeErrorResult({\n abi: IERC7412Abi,\n data: parsedError,\n });\n\n const oracleAddress = err.args![0] as Address;\n const oracleQuery = err.args![1] as Hex;\n const signedRequiredData = await this.fetchOracleUpdateData(oracleQuery);\n const dataVerificationTx = this.generateDataVerificationTx(oracleAddress, signedRequiredData);\n\n return dataVerificationTx;\n }\n\n /**\n * Handles ERC7412 error by creating a price update tx which is prepended to the existing calls\n * @param error Error thrown by the call function\n * @param calls Multicall call data\n * @returns call array with ERC7412 fulfillOracleQuery transaction\n */\n public async handleErc7412Error(parsedError: Hash): Promise<Call3Value[]> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let err: any;\n\n try {\n err = decodeErrorResult({\n abi: IERC7412Abi,\n data: parsedError,\n });\n } catch (decodeErr) {\n this.sdk.logger.error('Decode Error: ', decodeErr);\n throw new Error('Handle ERC7412 error');\n }\n if (!['OracleDataRequired', 'FeeRequired', 'Errors'].includes(err?.errorName))\n throw new Error('Handle ERC7412 error');\n\n if (err?.errorName === 'Errors') {\n const oracleErrors = err.args[0] as Hex[];\n let oracleCalls: Call3Value[] = [];\n const batchedOracleErrors = batchArray<Hex>(oracleErrors, 10);\n\n for (const oracleErrors of batchedOracleErrors) {\n const promiseOracleCalls = oracleErrors.map((oracleError) => {\n return this.handleErc7412Error(oracleError);\n });\n const resolvedCalls = await Promise.all(promiseOracleCalls);\n oracleCalls = [...oracleCalls, ...resolvedCalls.flat()];\n }\n\n return oracleCalls.flat();\n }\n\n if (err?.errorName === 'OracleDataRequired') {\n return [await this.handleOracleDataRequiredError(parsedError)];\n }\n\n // this.sdk.logger.info('Fee Required oracle error. Adding fee to tx.value', err);\n // if (!calls.length) throw new Error('Handle ERC7412 error: Calls.length == 0');\n //\n // calls[0].value = err.args[0] as bigint;\n\n return [];\n }\n\n /**\n * Generates Call3Value tx for Price update data of Oracle\n * @param oracleContract Oracle Contract address\n * @param signedRequiredData Encoded Price Update data\n * @returns Transaction Request for Oracle price update\n */\n public generateDataVerificationTx(_oracleContract: Hex, signedRequiredData: string): Call3Value {\n const priceUpdateCall: Call3Value = {\n target: ORACLE_PROXY_BY_CHAIN[this.sdk.rpcConfig.chainId],\n callData: encodeFunctionData({\n abi: IERC7412Abi as unknown as Abi,\n functionName: 'fulfillOracleQuery',\n args: [signedRequiredData],\n }),\n value: 0n,\n requireSuccess: false,\n };\n return priceUpdateCall;\n }\n\n /**\n * Calls the `functionName` on `contractAddress` target using the Multicall contract. If the call requires\n * a price update, ERC7412 price update tx is prepended to the tx.\n * @param contractAddress Target contract address for the call\n * @param abi Contract ABI\n * @param functionName Function to be called on the contract\n * @param args Arguments list for the function call\n * @param calls Array of Call3Value calls for Multicall contract\n * @returns Response from the contract function call\n */\n public async callErc7412({ contractAddress, abi, args, functionName, calls = [] }: WriteContractParams) {\n const multicallInstance = await this.sdk.contracts.getMulticallInstance();\n\n const currentCall: Call3Value = {\n target: contractAddress,\n callData: encodeFunctionData({\n abi: abi as Abi,\n functionName: functionName,\n args: args,\n }),\n value: 0n,\n requireSuccess: true,\n };\n\n calls.push(currentCall);\n\n const publicClient = this.sdk.getPublicClient();\n\n const oracleCalls = await this.getMissingOracleCalls(calls);\n const multicallData = encodeFunctionData({\n abi: multicallInstance.abi,\n functionName: 'aggregate3Value',\n args: [[...oracleCalls, ...calls]],\n });\n\n const totalValue = [...oracleCalls, ...calls].reduce((acc, tx) => {\n return acc + (tx.value || 0n);\n }, 0n);\n\n const finalTx = {\n account: this.sdk.accountAddress,\n to: multicallInstance.address,\n data: multicallData,\n value: totalValue,\n };\n\n const response = await publicClient.call(finalTx);\n this.sdk.logger.info('=== response', response);\n if (!response.data) throw new Error('Error decoding call data');\n const multicallResult: Result[] = this.decodeResponse(\n multicallInstance.abi,\n 'aggregate3Value',\n response.data as Hex,\n ) as unknown as Result[];\n\n const returnData = multicallResult.at(-1);\n\n if (!returnData?.success) throw new Error('Error decoding call data');\n\n const decodedResult = this.decodeResponse(abi, functionName, returnData.returnData);\n return decodedResult;\n }\n\n /**\n * Calls the `functionName` on `contractAddress` target using the Multicall contract. If the call requires\n * a price update, ERC7412 price update tx is prepended to the tx.\n * @param contractAddress Target contract address for the call\n * @param abi Contract ABI\n * @param functionName Function to be called on the contract\n * @param argsList Array of arguments list for the function call\n * @param calls Array of Call3Value calls for Multicall contract\n * @returns Array of responses from the contract function call for the multicalls\n */\n public async multicallErc7412({\n contractAddress,\n abi,\n functionName,\n args: argsList,\n calls = [],\n }: WriteContractParams) {\n const multicallInstance = await this.sdk.contracts.getMulticallInstance();\n // Format the args to the required array format\n argsList = argsList.map((args) => (Array.isArray(args) ? args : [args]));\n\n argsList.forEach((args) => {\n const currentCall: Call3Value = {\n target: contractAddress,\n callData: encodeFunctionData({\n abi: abi as Abi,\n functionName: functionName,\n args: args as unknown[],\n }),\n value: 0n,\n requireSuccess: true,\n };\n calls.push(currentCall);\n });\n calls = calls.map((call) => {\n return {\n ...call,\n requireSuccess: call.value === 0n ? true : false,\n };\n });\n const oracleCalls = await this.getMissingOracleCalls(calls);\n\n const numCalls = calls.length - oracleCalls.length;\n\n const publicClient = this.sdk.getPublicClient();\n\n const totalValue = [...oracleCalls, ...calls].reduce((acc, tx) => {\n return acc + (tx.value || 0n);\n }, 0n);\n\n const multicallData = encodeFunctionData({\n abi: multicallInstance.abi,\n functionName: 'aggregate3Value',\n args: [[...oracleCalls, ...calls]],\n });\n\n const finalTx = {\n account: this.sdk.accountAddress,\n to: multicallInstance.address,\n data: multicallData,\n value: totalValue,\n };\n\n const response = await publicClient.call(finalTx);\n const multicallResult: Result[] = this.decodeResponse(\n multicallInstance.abi,\n 'aggregate3Value',\n response.data as Hex,\n ) as unknown as Result[];\n\n const callsToDecode = multicallResult.slice(-numCalls);\n\n const decodedResult = callsToDecode.map((result) => this.decodeResponse(abi, functionName, result.returnData));\n return decodedResult;\n }\n protected isWriteContractParams(data: WriteErc7412): data is WriteContractParams {\n return (data as WriteContractParams).contractAddress !== undefined;\n }\n\n /**\n * Simulates the `functionName` on `contractAddress` target using the Multicall contract and returns the\n * final transaction call with ERC7412 price update data if required\n * @param contractAddress Target contract address for the call\n * @param abi Contract ABI\n * @param functionName Function to be called on the contract\n * @param args Arguments list for the function call\n * @param calls Array of Call3Value calls for Multicall contract\n * @param override Override parameters for the transaction\n * @returns Final transaction call with ERC7412 price update data if required\n */\n public async writeErc7412(\n data: WriteErc7412,\n override: OverrideParamsWrite = {\n shouldRevertOnTxFailure: true,\n },\n ): Promise<TransactionData> {\n const calls: Call3Value[] = data.calls ?? [];\n const multicallInstance = await this.sdk.contracts.getMulticallInstance();\n\n if (this.isWriteContractParams(data)) {\n const { contractAddress, abi, functionName, args } = data as WriteContractParams;\n const currentCall: Call3Value = {\n target: contractAddress,\n callData: encodeFunctionData({\n abi: abi as Abi,\n functionName: functionName,\n args: args,\n }),\n value: 0n,\n requireSuccess: true,\n };\n calls.push(currentCall);\n }\n\n const multicallData = encodeFunctionData({\n abi: multicallInstance.abi,\n functionName: 'aggregate3Value',\n args: [calls],\n });\n\n let totalValue = 0n;\n for (const tx of calls) {\n totalValue += tx.value || 0n;\n }\n\n const finalTx = {\n account: override.account || this.sdk.accountAddress,\n to: multicallInstance.address,\n data: multicallData,\n value: totalValue,\n };\n\n const publicClient = this.sdk.getPublicClient();\n\n if (override.shouldRevertOnTxFailure) await publicClient.call(finalTx);\n\n return this._fromCallDataToTransactionData(finalTx);\n }\n\n /**\n * Calls the `functionName` on `contractAddress` target using the Multicall contract. If the call requires\n * a price update, ERC7412 price update tx is prepended to the tx.\n * @param contractAddress Target contract address for the call\n * @param abi Contract ABI\n * @param functionNames Function to be called on the contract\n * @param argsList Array of arguments list for the function call\n * @param calls Array of Call3Value calls for Multicall contract\n * @returns Array of responses from the contract function call for the multicalls\n */\n public async multicallMultifunctionErc7412(\n {\n contractAddress,\n abi,\n functionNames,\n args: argsList,\n calls = [],\n }: Omit<WriteContractParams, 'functionName'> & { functionNames: string[] },\n override: OverrideParamsRead = {},\n ) {\n const multicallInstance = await this.sdk.contracts.getMulticallInstance();\n\n // Format the args to the required array format\n argsList = argsList.map((args) => (Array.isArray(args) ? args : [args]));\n\n if (argsList.length != functionNames.length) {\n throw new Error(\"Inconsistent data: args and functionName don't match\");\n }\n argsList.forEach((args, index) => {\n const currentCall: Call3Value = {\n target: contractAddress,\n callData: encodeFunctionData({\n abi: abi as Abi,\n functionName: functionNames[index],\n args: args as unknown[],\n }),\n value: 0n,\n requireSuccess: true,\n };\n calls.push(currentCall);\n });\n\n const publicClient = this.sdk.getPublicClient();\n const oracleCalls = await this.getMissingOracleCalls(calls);\n\n const multicallData = encodeFunctionData({\n abi: multicallInstance.abi,\n functionName: 'aggregate3Value',\n args: [[...oracleCalls, ...calls]],\n });\n\n let totalValue = 0n;\n for (const tx of [...oracleCalls, ...calls]) {\n totalValue += tx.value || 0n;\n }\n\n const finalTx = {\n account: override.account || this.sdk.accountAddress,\n to: multicallInstance.address,\n data: multicallData,\n value: totalValue,\n };\n\n const response = await publicClient.call(finalTx);\n this.sdk.logger.info('=== response', response);\n const multicallResult: Result[] = this.decodeResponse(\n multicallInstance.abi,\n 'aggregate3Value',\n response.data as Hex,\n ) as unknown as Result[];\n\n const callsToDecode = multicallResult.slice(-oracleCalls.length);\n\n const decodedResult = callsToDecode.map((result, idx) =>\n this.decodeResponse(abi, functionNames[idx], result.returnData),\n );\n return decodedResult;\n }\n\n public async getMissingOracleCalls(\n calls: Call3Value[],\n oracleCalls: Call3Value[] = [],\n {\n attemps = MAX_ERC7412_RETRIES,\n account,\n stateOverride,\n }: { account?: Address; attemps?: number; stateOverride?: StateOverride } = {},\n ): Promise<Call3Value[]> {\n const publicClient = this.sdk.getPublicClient();\n const totalValue = [...oracleCalls, ...calls].reduce((acc, tx) => {\n return acc + (tx.value || 0n);\n }, 0n);\n this.sdk.logger.info('=== init data', { oracleCalls, calls, attemps });\n const multicallInstance = await this.sdk.contracts.getMulticallInstance();\n const multicallData = encodeFunctionData({\n abi: multicallInstance.abi,\n functionName: 'aggregate3Value',\n args: [[...oracleCalls, ...calls]],\n });\n\n const parsedTx = {\n account: account || this.sdk.accountAddress,\n to: multicallInstance.address,\n data: multicallData,\n value: totalValue,\n stateOverride,\n };\n\n try {\n await publicClient.call(parsedTx);\n return oracleCalls;\n } catch (error) {\n const parsedError = parseError(error as CallExecutionError);\n this.sdk.logger.error('=== parsedError in getMissingOracleCalls', parsedError);\n const shouldRetry = this.shouldRetryLogic(error, attemps);\n console.log('=== shouldRetry', { shouldRetry, error, attemps, parsedError });\n\n if (!shouldRetry) return oracleCalls;\n const data = await this.handleErc7412Error(parsedError);\n\n return await this.getMissingOracleCalls(calls, [...oracleCalls, ...data], {\n account,\n attemps: attemps - 1,\n stateOverride,\n });\n }\n }\n\n _fromCall3ToTransactionData(call: Call3Value): TransactionData {\n return {\n to: call.target,\n data: call.callData,\n value: call?.value?.toString() ?? '0',\n } as TransactionData;\n }\n\n _fromTransactionDataToCall3(data: TransactionData, requireSuccess = true): Call3Value {\n return {\n target: data.to,\n callData: data.data,\n value: BigInt(data.value || 0),\n requireSuccess,\n } as Call3Value;\n }\n\n _fromCallDataToTransactionData(calls: CallParameters): TransactionData {\n return {\n to: calls.to as Address,\n\n data: calls.data as Hash,\n value: calls?.value?.toString() ?? '0',\n } as TransactionData;\n }\n _fromTransactionDataToCallData(data: TransactionData): CallParameters {\n return {\n account: this.sdk.accountAddress,\n to: data.to,\n data: data.data,\n value: BigInt(data.value || 0),\n } as CallParameters;\n }\n\n async processTransactions(data: Call3Value[], override: OverrideParamsWrite): Promise<WriteReturnType> {\n const useOracleCall = override.useOracleCalls ?? true;\n\n const oracleCalls = useOracleCall\n ? ((await this.getMissingOracleCalls(data, undefined, {\n account: override.account,\n stateOverride: override?.stateOverride?.reduce(\n (acc, state) => {\n const includedIndex = acc.findIndex((s) => s.address === state.address);\n const included = override?.stateOverride?.[includedIndex];\n\n if (!included && state.stateDiff) acc.push(state);\n\n if (included) {\n acc[includedIndex] = {\n address: state.address,\n stateDiff: [...state.stateDiff, ...included.stateDiff],\n };\n }\n return acc;\n },\n [] as { address: Address; stateDiff: StateMapping }[],\n ),\n })) ?? undefined)\n : [];\n\n const txs = [\n ...(!override.useMultiCall ? (override.prepend || []).map((a) => this._fromTransactionDataToCall3(a, true)) : []),\n ...oracleCalls,\n ...data,\n ];\n if (!override.useMultiCall && !override.submit) return txs.map(this.sdk.utils._fromCall3ToTransactionData);\n\n const tx = await this.sdk.utils.writeErc7412({ calls: txs }, override);\n if (!override.submit) return [...(override.prepend || []), tx];\n\n return this.sdk.executeTransaction(this.sdk.utils._fromTransactionDataToCallData(tx));\n }\n\n shouldRetryLogic(error: unknown, attemps: number = 0): boolean {\n const parsedError = parseError(error as CallExecutionError);\n const isErc7412Error = this.isErc7412Error(parsedError);\n\n this.sdk.logger.error('=== parsedError in processTransactions ', {\n parsedError,\n isErc7412Error,\n });\n if (!attemps && !isErc7412Error) return false;\n if (!isErc7412Error) {\n return false;\n }\n\n return true;\n }\n\n isErc7412Error(parsedError: Hash): boolean {\n return (\n parsedError.startsWith(SIG_ORACLE_DATA_REQUIRED) ||\n parsedError.startsWith(SIG_FEE_REQUIRED) ||\n parsedError.startsWith(SIG_ERRORS)\n );\n }\n}\n","export const IERC7412Abi = [\n {\n type: 'function',\n name: 'fulfillOracleQuery',\n inputs: [{ name: 'signedOffchainData', type: 'bytes', internalType: 'bytes' }],\n outputs: [],\n stateMutability: 'payable',\n },\n {\n type: 'function',\n name: 'oracleId',\n inputs: [],\n outputs: [{ name: '', type: 'bytes32', internalType: 'bytes32' }],\n stateMutability: 'view',\n },\n {\n type: 'error',\n name: 'FeeRequired',\n inputs: [{ name: 'feeAmount', type: 'uint256', internalType: 'uint256' }],\n },\n {\n type: 'error',\n name: 'OracleDataRequired',\n inputs: [\n { name: 'oracleContract', type: 'address', internalType: 'address' },\n { name: 'oracleQuery', type: 'bytes', internalType: 'bytes' },\n ],\n },\n {\n type: 'error',\n name: 'Errors',\n inputs: [\n {\n type: 'bytes[]',\n name: 'revertReasons',\n },\n ],\n },\n];\n","import { Hex } from 'viem';\n\n// TODO: Generalize this. See https://github.com/usecannon/cannon/blob/main/packages/builder/src/error/index.ts\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function parseError(error: any): Hex {\n try {\n if (error.cause?.data) {\n return error.cause?.data;\n }\n if (error.cause?.cause?.data) {\n return error.cause?.cause?.data;\n }\n if (error.cause?.cause?.cause?.data) {\n return error.cause?.cause?.cause?.data;\n }\n if (error.cause?.cause?.error?.data) {\n return error.cause?.cause?.error?.data;\n }\n if (error.cause?.cause?.cause?.error?.data) {\n return error.cause?.cause?.cause?.error?.data;\n }\n } catch (err) {\n console.log('=== exception in erc7412 error parser:', err);\n }\n console.log('=== a', JSON.stringify(error, null, 2));\n // rethrow the error (and log it so we can see the original)\n console.error('=== got unknown error in erc7412 parse', error);\n return '0x';\n}\n","import { Address } from 'viem';\nimport { SUPPORTED_CHAINS } from '../../constants/chains';\n\nexport const ORACLE_PROXY_BY_CHAIN: Record<number, Address> = {\n [SUPPORTED_CHAINS.ARBITUM_SEPOLIA]: '0x59d6ec32e05900949d7fff679a4adc7f94f0208c',\n [SUPPORTED_CHAINS.ARBITRUM]: '0xe87ceB87b63267ef925E2897B629052eb815bB7d',\n [SUPPORTED_CHAINS.BASE]: '0xa03A0Be2f3B85B76765A442683d62E992972d816',\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: '0x4Bc47c016EE6Ead253152CCfe6427D0bC06F544c',\n};\n","import { Address, encodeFunctionData, formatEther, Hex, parseUnits } from 'viem';\nimport { SynthetixSdk } from '..';\nimport { ZERO_ADDRESS } from '../constants/common';\nimport { CoreRepository } from '../interface/Core';\nimport { OverrideParamsWrite, WriteReturnType } from '../interface/commonTypes';\nimport { Call3Value } from '../interface/contractTypes';\n\n/**\n * Class for interacting with Synthetix V3 core contracts\n * @remarks\n *\n */\nexport class Core implements CoreRepository {\n sdk: SynthetixSdk;\n defaultAccountId?: bigint;\n accountIds: bigint[];\n\n constructor(synthetixSdk: SynthetixSdk) {\n this.sdk = synthetixSdk;\n this.accountIds = [];\n }\n\n async initCore() {\n await this.getAccountIds();\n }\n\n /**\n * Returns the Owner wallet address for an account ID\n * @param accountId - Account ID\n * @returns string - Address of the account owning the accountId\n */\n public async getAccountOwner(accountId: bigint): Promise<Hex> {\n const coreProxy = await this.sdk.contracts.getCoreProxyInstance();\n const response = await this.sdk.utils.callErc7412({\n contractAddress: coreProxy.address,\n abi: coreProxy.abi,\n functionName: 'getAccountOwner',\n args: [accountId],\n });\n\n this.sdk.logger.info(`Core account Owner for id ${accountId} is ${response}`);\n\n return response as Hex;\n }\n\n /**\n * Get the address of the USD stablecoin token\n *\n * @returns Address of the USD stablecoin token\n */\n public async getUsdToken(): Promise<Hex> {\n const coreProxy = await this.sdk.contracts.getCoreProxyInstance();\n const response = await this.sdk.utils.callErc7412({\n contractAddress: coreProxy.address,\n abi: coreProxy.abi,\n functionName: 'getUsdToken',\n args: [],\n });\n\n this.sdk.logger.info('USD Token address: ', response);\n return response as Hex;\n }\n\n /**\n * Get the core account IDs owned by an address.\n * Fetches the account IDs for the given address by checking the balance of\n * the AccountProxy contract, which is an NFT owned by the address.\n * If no address is provided, uses the connected wallet address.\n * @param address The address to get accounts for. Uses connected address if not provided.\n * @param defaultAccountId The default account ID to set after fetching.\n * @returns A list of account IDs owned by the address\n */\n\n public async getAccountIds({\n address: accountAddress = this.sdk.accountAddress || ZERO_ADDRESS,\n accountId: defaultAccountId = undefined,\n }: {\n address?: string;\n accountId?: bigint;\n } = {}): Promise<bigint[]> {\n if (accountAddress == ZERO_ADDRESS) {\n throw new Error('Invalid address');\n }\n\n const accountProxy = await this.sdk.contracts.getAccountProxyInstance();\n const balance = await accountProxy.read.balanceOf([accountAddress]);\n this.sdk.logger.info('balance', balance);\n\n const argsList = [];\n\n for (let index = 0; index < Number(balance); index++) {\n argsList.push([accountAddress, index]);\n }\n const accountIds = (await this.sdk.utils.multicallErc7412({\n contractAddress: accountProxy.address,\n abi: accountProxy.abi,\n functionName: 'tokenOfOwnerByIndex',\n args: argsList,\n })) as unknown[] as bigint[];\n\n // Set Core account ids\n this.accountIds = accountIds;\n this.sdk.logger.info('accountIds', accountIds);\n if (defaultAccountId) {\n this.defaultAccountId = defaultAccountId;\n } else if (this.accountIds.length > 0) {\n this.defaultAccountId = this.accountIds[0];\n this.sdk.logger.info('Using default account id as ', this.defaultAccountId);\n }\n return accountIds;\n }\n\n /**\n * Get the available collateral for an account for a specified collateral type\n * of ``token_address``\n * Fetches the amount of undelegated collateral available for withdrawal\n * for a given token and account.\n * @param tokenAddress The address of the collateral token\n * @param accountId The ID of the account to check. Uses default if not provided.\n * @returns The available collateral as an ether value.\n */\n public async getAvailableCollateral({\n tokenAddress,\n accountId = this.defaultAccountId,\n }: {\n tokenAddress: Address;\n accountId?: bigint;\n }): Promise<string> {\n if (!accountId) throw new Error('Invalid account ID');\n\n const coreProxy = await this.sdk.contracts.getCoreProxyInstance();\n\n const availableCollateral = await this.sdk.utils.callErc7412({\n contractAddress: coreProxy.address,\n abi: coreProxy.abi,\n functionName: 'getAccountAvailableCollateral',\n args: [accountId, tokenAddress],\n });\n\n return formatEther(availableCollateral as bigint);\n }\n\n /**\n * Retrieves the unique system preferred pool\n * @returns poolId The id of the pool that is currently set as preferred in the system.\n */\n public async getPreferredPool(): Promise<bigint> {\n const coreProxy = await this.sdk.contracts.getCoreProxyInstance();\n\n const preferredPool = await this.sdk.utils.callErc7412({\n contractAddress: coreProxy.address,\n abi: coreProxy.abi,\n functionName: 'getPreferredPool',\n args: [],\n });\n this.sdk.logger.info(preferredPool);\n return preferredPool as bigint;\n }\n\n public async createAccount(\n accountId?: bigint,\n override: Omit<OverrideParamsWrite, 'useOracleCalls'> = { shouldRevertOnTxFailure: false },\n ): Promise<WriteReturnType> {\n const txArgs = [];\n if (accountId != undefined) {\n txArgs.push(accountId);\n }\n\n const coreProxy = await this.sdk.contracts.getCoreProxyInstance();\n const createAccountTx: Call3Value = {\n target: coreProxy.address,\n callData: encodeFunctionData({\n abi: coreProxy.abi,\n functionName: 'createAccount',\n args: txArgs,\n }),\n value: 0n,\n requireSuccess: true,\n };\n const txs = [createAccountTx];\n return this.sdk.utils.processTransactions(txs, { ...override, useOracleCalls: false });\n }\n\n public async deposit(\n {\n tokenAddress,\n amount,\n decimals = 18,\n accountId = this.defaultAccountId,\n }: {\n tokenAddress: string;\n amount: number;\n decimals: number;\n accountId?: bigint;\n },\n override: OverrideParamsWrite = { shouldRevertOnTxFailure: false },\n ): Promise<WriteReturnType> {\n if (!accountId) throw new Error('Invalid account ID');\n\n const amountInWei = parseUnits(amount.toString(), decimals);\n const coreProxy = await this.sdk.contracts.getCoreProxyInstance();\n\n const depositTx: Call3Value = {\n target: coreProxy.address,\n callData: encodeFunctionData({\n abi: coreProxy.abi,\n functionName: 'deposit',\n args: [accountId, tokenAddress, amountInWei],\n }),\n value: 0n,\n requireSuccess: true,\n };\n\n const txs = [depositTx];\n return this.sdk.utils.processTransactions(txs, override);\n }\n\n public async withdraw(\n {\n tokenAddress,\n amount,\n decimals = 18,\n accountId = this.defaultAccountId,\n }: {\n tokenAddress: string;\n amount: number;\n decimals: number;\n accountId?: bigint;\n },\n override: OverrideParamsWrite = { shouldRevertOnTxFailure: false },\n ): Promise<WriteReturnType> {\n if (!accountId) throw new Error('Account ID is required for withdrawal');\n\n const amountInWei = parseUnits(amount.toString(), decimals);\n const coreProxy = await this.sdk.contracts.getCoreProxyInstance();\n\n const withdrawTx: Call3Value = {\n target: coreProxy.address,\n callData: encodeFunctionData({\n abi: coreProxy.abi,\n functionName: 'withdraw',\n args: [accountId, tokenAddress, amountInWei],\n }),\n value: 0n,\n requireSuccess: true,\n };\n\n const txs = [withdrawTx];\n return this.sdk.utils.processTransactions(txs, override);\n }\n\n public async delegateCollateral(\n {\n tokenAddress,\n amount,\n poolId,\n leverage,\n accountId = this.defaultAccountId,\n }: {\n tokenAddress: string;\n amount: number;\n poolId: bigint;\n leverage: number;\n accountId?: bigint;\n },\n override: OverrideParamsWrite = { shouldRevertOnTxFailure: false },\n ): Promise<WriteReturnType> {\n if (!accountId) throw new Error('Invalid account ID')