import type { Maybe } from "@rarible/types" import type { Link } from "@imtbl/imx-sdk" import { Configuration } from "@rarible/ethereum-api-client" import type { ImxEnv } from "@rarible/immutable-wallet" import { convertFees } from "../common/convert-fees" import { IMX_ENV_CONFIG } from "../config/env" import { ImxTradesControllerApi } from "../apis/trades" import type { Erc721AssetRequest } from "../nft/domain" import { retry } from "../common/utils" import type { BuyRequest, BuyResponse, CancelOrderRequest, CancelOrderResponse, SellRequest, SellResponse, SellResponseRaw, } from "./domain" export async function sell( link: Maybe, request: SellRequest, ): Promise { if (link === undefined) { throw new Error("Wallet undefined") } const { makeAssetType: { tokenId, contract }, takeAssetType, amount, payouts, originFees } = request const currencyContract = takeAssetType.assetClass === "ERC20" ? takeAssetType.contract : undefined const orderId = await link.sell({ tokenId, tokenAddress: contract, fees: convertFees([...payouts, ...originFees]), amount, ...currencyContract ? { currencyAddress: currencyContract } : {}, }) as unknown as number return { orderId, } as SellResponse } export async function buy( env: ImxEnv, link: Maybe, request: BuyRequest, token: Erc721AssetRequest ): Promise { if (link === undefined) { throw new Error("Wallet undefined") } const { orderId, fee } = request const buyResult = await link.buy({ orderIds: [orderId], fees: convertFees(fee), }) const tradeResult = buyResult.result?.[orderId] if (tradeResult.status === "error") { throw new Error("Trade unsuccessful: " + tradeResult.message) } let txId = undefined try { txId = await retry(20, 2000, async () => { const { apiAddressV1 } = IMX_ENV_CONFIG[env] const balanceApiConfig = new Configuration({ basePath: apiAddressV1 }) const api = new ImxTradesControllerApi(balanceApiConfig) const { result } = await api.getTrades({ tokenType: token.assetClass, tokenAddress: token.contract, tokenId: token.tokenId, }) const trade = result.find((trade) => trade.b.order_id.toString() === orderId) if (!trade) { throw new Error("Can't find trade with orderid " + orderId) } if (tradeResult.status === "success") { return trade.transaction_id } }) } catch (e: any) { console.error("Error while fetching trade", e) } return { txId, } } export async function cancel( link: Maybe, request: CancelOrderRequest, ): Promise { if (link === undefined) { throw new Error("Wallet undefined") } const { orderId } = request const result = await link.cancel({ orderId, }) return { orderId: (result as unknown as SellResponseRaw).order_id.toString(), } }