diff --git a/apollo/src/aggregation/aggregation.history.graphql b/apollo/src/aggregation/aggregation.history.graphql index 3a67fe19..042a8754 100644 --- a/apollo/src/aggregation/aggregation.history.graphql +++ b/apollo/src/aggregation/aggregation.history.graphql @@ -112,6 +112,7 @@ type Query { queryLnBridgeRelayInfos(fromChain: String, toChain: String, version: String, bridge: String, relayer: String, row: Int, page: Int): LnBridgeRelayInfos sortedLnBridgeRelayInfos(fromChain: String, toChain: String, version: String, bridge: String, token: String, row: Int, amount: String, decimals: Int): SortedLnBridgeRelayInfos queryLnBridgeSupportChains(tokenKey: String): [SupportChains] + queryMaxTransfer(fromChain: String, toChain: String, bridge: String, token: String, balance: String): BigInt } type Mutation { diff --git a/apollo/src/aggregation/aggregation.resolver.ts b/apollo/src/aggregation/aggregation.resolver.ts index 9d174231..f22ebeaf 100644 --- a/apollo/src/aggregation/aggregation.resolver.ts +++ b/apollo/src/aggregation/aggregation.resolver.ts @@ -413,4 +413,65 @@ export class AggregationResolver { records: sortedRelayers.sort((l, r) => l.point - r.point).map((item) => item.record), }; } + + /** + * For one relayer + * userBalance, transferLimitV2(margin), transferLimitV3 baseFee, liquidityFeeRate, protocolFee + * suppose user transfer amount is X + * then totalFee = X * liquidityFeeRate / 100000 + baseFee + protocolFee + * 1. totalFee + X <= userBalance => X <= (userBalance - baseFee - protocolFee)/(1 + liquidityFeeRate / 100000) + * 2. V2: totalFee + X <= transferLimitV2 => X <= (transferLimitV2 - baseFee - protocolFee)/(1 + liquidityFeeRate / 100000) + * 3. V3: X <= transferLimitV3 => X <= transferLimitV3 + */ + @Query() + async queryMaxTransfer( + @Args('fromChain') fromChain: string, + @Args('toChain') toChain: string, + @Args('bridge') bridge: string, + @Args('token') token: string, + @Args('balance') balance: string, + ) { + const sendToken = token?.toLowerCase(); + const baseFilters = { fromChain, toChain, sendToken, bridge }; + + const where = { + ...baseFilters, + }; + + const records = await this.aggregationService.queryLnBridgeRelayInfos({ + skip: 0, + where, + }); + var maxTransferAmount = BigInt(0); + const now = Math.floor(Date.now() / 1000); + const liquidityFeeScale = BigInt(100000); + for (const record of records.records) { + // offline + if (record.heartbeatTimestamp + this.heartbeatTimeout < now || record.paused) { + continue; + } + + const fixFee = BigInt(record.baseFee) + BigInt(record.protocolFee); + const userBalanceRestrict = (BigInt(balance) - fixFee) * liquidityFeeScale / (liquidityFeeScale + BigInt(record.liquidityFeeRate)); + let limitRestrict = record.version === 'lnv2' ? + (BigInt(record.margin) - fixFee) * liquidityFeeScale / (liquidityFeeScale + BigInt(record.liquidityFeeRate)) : + BigInt(record.transferLimit); + + try { + const softTransferLimit = BigInt(record.softTransferLimit); + if (limitRestrict > softTransferLimit && softTransferLimit > 0) { + limitRestrict = softTransferLimit; + } + } catch(e) { + console.log(`get softTransferLimit failed ${record.id}, exception: ${e}`); + continue; + } + + const limit = limitRestrict < userBalanceRestrict ? limitRestrict : userBalanceRestrict; + if (maxTransferAmount < limit) { + maxTransferAmount = limit; + } + } + return maxTransferAmount; + } } diff --git a/apollo/src/graphql.ts b/apollo/src/graphql.ts index 44e5eeba..44d0bf4f 100644 --- a/apollo/src/graphql.ts +++ b/apollo/src/graphql.ts @@ -38,6 +38,8 @@ export abstract class IQuery { abstract sortedLnBridgeRelayInfos(fromChain?: Nullable, toChain?: Nullable, version?: Nullable, bridge?: Nullable, token?: Nullable, row?: Nullable, amount?: Nullable, decimals?: Nullable): Nullable | Promise>; abstract queryLnBridgeSupportChains(tokenKey?: Nullable): Nullable[]> | Promise[]>>; + + abstract queryMaxTransfer(fromChain?: Nullable, toChain?: Nullable, bridge?: Nullable, token?: Nullable, balance?: Nullable): Nullable | Promise>; } export class HistoryRecord {