{"version":3,"sources":["../src/xlinkSdkUtils/timelockFromEVM.ts"],"sourcesContent":["import { Client, encodeFunctionData, zeroAddress } from \"viem\"\nimport { estimateGas, readContract } from \"viem/actions\"\nimport { BridgeEndpointAbi } from \"../evmUtils/contractAbi/bridgeEndpoint\"\nimport { BridgeTimeLockAbi } from \"../evmUtils/contractAbi/bridgeTimeLock\"\nimport {\n  getEVMContractCallInfo,\n  getEVMTokenContractInfo,\n  numberFromSolidityContractNumber,\n} from \"../evmUtils/xlinkContractHelpers\"\nimport { BigNumber } from \"../utils/BigNumber\"\nimport { UnsupportedChainError } from \"../utils/errors\"\nimport { decodeHex } from \"../utils/hexHelpers\"\nimport { isNotNull } from \"../utils/typeHelpers\"\nimport {\n  KnownChainId,\n  KnownTokenId,\n  _allKnownEVMTokens,\n} from \"../utils/types/knownIds\"\nimport { EVMAddress, SDKNumber, toSDKNumberOrUndefined } from \"./types\"\nimport { SDKGlobalContext } from \"./types.internal\"\nimport { nativeCurrencyAddress } from \"../evmUtils/addressHelpers\"\n\nexport interface TimeLockedAsset {\n  id: string\n  chain: KnownChainId.EVMChain\n  token: KnownTokenId.EVMToken\n  amount: SDKNumber\n  releaseTime: Date\n}\n\nconst getTimeLockContractCallInfo = async (\n  ctx: SDKGlobalContext,\n  chain: KnownChainId.EVMChain,\n): Promise<\n  | undefined\n  | {\n      client: Client\n      timeLockContractAddress: EVMAddress\n    }\n> => {\n  const info = await getEVMContractCallInfo(ctx, chain)\n  if (info == null) return\n\n  const timeLockContractAddress =\n    info.timeLockContractAddress ??\n    (await readContract(info.client, {\n      abi: BridgeEndpointAbi,\n      address: info.bridgeEndpointContractAddress,\n      functionName: \"timeLock\",\n    }).catch(err => {\n      console.groupCollapsed(\n        `Failed to read timeLock contract address from ${info.bridgeEndpointContractAddress} (${chain})`,\n      )\n      console.debug(err)\n      console.groupEnd()\n      return zeroAddress\n    }))\n  if (timeLockContractAddress === zeroAddress) return\n\n  return { client: info.client, timeLockContractAddress }\n}\n\nexport interface GetTimeLockedAssetsInput {\n  walletAddress: EVMAddress\n  chains: KnownChainId.EVMChain[]\n}\nexport interface GetTimeLockedAssetsOutput {\n  assets: TimeLockedAsset[]\n}\nexport async function getTimeLockedAssetsFromEVM(\n  ctx: SDKGlobalContext,\n  input: GetTimeLockedAssetsInput,\n): Promise<GetTimeLockedAssetsOutput> {\n  const promises = input.chains.map(async chain => {\n    const timeLockCallInfo = await getTimeLockContractCallInfo(ctx, chain)\n    if (timeLockCallInfo == null) return []\n\n    const tokenCallInfos = (\n      await Promise.all(\n        _allKnownEVMTokens.map(token =>\n          getEVMTokenContractInfo(ctx, chain, token).then(info =>\n            info == null || info.tokenContractAddress === nativeCurrencyAddress\n              ? null\n              : { ...info, chain, token },\n          ),\n        ),\n      )\n    ).filter(isNotNull)\n\n    const agreements = (\n      await Promise.all(\n        tokenCallInfos.map(info =>\n          readContract(timeLockCallInfo.client, {\n            abi: BridgeTimeLockAbi,\n            address: timeLockCallInfo.timeLockContractAddress,\n            functionName: \"agreementsByUser\",\n            args: [input.walletAddress, 0, info.tokenContractAddress, \"0x\"],\n          }).then(agreementId =>\n            agreementId === 0n ? [] : [{ agreementId, info }],\n          ),\n        ),\n      )\n    ).flat()\n\n    return Promise.all(\n      agreements.map(async ({ agreementId, info }) => {\n        const agreement = await readContract(timeLockCallInfo.client, {\n          abi: BridgeTimeLockAbi,\n          address: timeLockCallInfo.timeLockContractAddress,\n          functionName: \"agreements\",\n          args: [agreementId],\n        })\n        return {\n          id: String(agreementId),\n          chain: info.chain,\n          token: info.token,\n          amount: toSDKNumberOrUndefined(\n            numberFromSolidityContractNumber(agreement[0]),\n          ),\n          releaseTime: new Date(agreement[6] * 1000),\n        }\n      }),\n    )\n  })\n\n  return {\n    assets: (await Promise.all(promises)).flat(),\n  }\n}\n\nexport interface ClaimTimeLockedAssetsInput {\n  chain: KnownChainId.EVMChain\n  walletAddress: EVMAddress\n  lockedAssetIds: string[]\n  sendTransaction: (tx: {\n    from: EVMAddress\n    to: EVMAddress\n    data: Uint8Array\n    recommendedGasLimit: SDKNumber\n  }) => Promise<{\n    txHash: string\n  }>\n}\nexport interface ClaimTimeLockedAssetsOutput {\n  txHash: string\n}\nexport const claimTimeLockedAssetsFromEVM = async (\n  ctx: SDKGlobalContext,\n  input: ClaimTimeLockedAssetsInput,\n): Promise<undefined | ClaimTimeLockedAssetsOutput> => {\n  const info = await getTimeLockContractCallInfo(ctx, input.chain)\n  if (info == null) throw new UnsupportedChainError(input.chain)\n\n  const functionData = encodeFunctionData({\n    abi: BridgeTimeLockAbi,\n    functionName: \"claim\",\n    args: [\n      input.lockedAssetIds.map(id =>\n        BigNumber.toBigInt({ roundingMode: BigNumber.roundDown }, id),\n      ),\n    ],\n  })\n  const estimated = await estimateGas(info.client, {\n    account: input.walletAddress,\n    to: info.timeLockContractAddress,\n    data: functionData,\n  })\n    .then(n => BigNumber.round({ precision: 0 }, BigNumber.mul(n, 1.2)))\n    .catch(\n      // add a fallback in case estimate failed\n      () =>\n        // https://bscscan.com/tx/0x28a81312ca7bc93e7ef07867c9906a41b251ea3ea630b0a4837bdb3066489b32\n        1 * 1e6,\n    )\n  return await input.sendTransaction({\n    from: input.walletAddress,\n    to: info.timeLockContractAddress,\n    data: decodeHex(functionData),\n    recommendedGasLimit: toSDKNumberOrUndefined(estimated),\n  })\n}\n"],"mappings":"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","names":[]}