Skip to content

Commit

Permalink
fix: xcm fees (#117)
Browse files Browse the repository at this point in the history
* fix: xcm fees

* fix: typo
  • Loading branch information
qiweiii committed Mar 7, 2024
1 parent 7927351 commit 3972b7b
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 21 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,5 @@
"jest": "^28.1.1",
"typescript": "^4.7.4"
},
"stableVersion": "0.1.5-34"
"stableVersion": "0.1.5-35"
}
2 changes: 1 addition & 1 deletion src/adapters/acala/acala-configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const acalaRouteConfigs = createRouteConfigs("acala", [
to: "polkadot",
token: "DOT",
xcm: {
fee: { token: "DOT", amount: "469417452" },
fee: { token: "DOT", amount: "19978738" },
},
},
{
Expand Down
16 changes: 11 additions & 5 deletions src/adapters/polkadot.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Storage } from "@acala-network/sdk/utils/storage";
import { AnyApi, FixedPointNumber as FN } from "@acala-network/sdk-core";
import { combineLatest, map, Observable, from } from "rxjs";
import { combineLatest, map, Observable } from "rxjs";

import { SubmittableExtrinsic } from "@polkadot/api/types";
import { DeriveBalancesAll } from "@polkadot/api-derive/balances/types";
Expand All @@ -14,15 +14,18 @@ import { BalanceData, BasicToken, TransferParams } from "../types";
import {
createRouteConfigs,
getDestAccountInfo,
getPolkadotXcmDeliveryFee,
validateAddress,
} from "../utils";

export const polkadotRouteConfigs = createRouteConfigs("polkadot", [
{
to: "acala",
token: "DOT",
xcm: { fee: { token: "DOT", amount: "3549633" }, weightLimit: "Unlimited" },
xcm: {
fee: { token: "DOT", amount: "1222070" },
deliveryFee: { token: "DOT", amount: "399000000" },
weightLimit: "Unlimited",
},
},
{
to: "hydradx",
Expand All @@ -48,6 +51,7 @@ export const kusamaRouteConfigs = createRouteConfigs("kusama", [
token: "KSM",
xcm: {
fee: { token: "KSM", amount: "44163610" },
deliveryFee: { token: "KSM", amount: "1336666329" },
weightLimit: "Unlimited",
},
},
Expand Down Expand Up @@ -162,6 +166,8 @@ class BasePolkadotAdapter extends BaseCrossChainAdapter {
throw new ApiNotFound(this.chain.id);
}

const xcmDeliveryFee = this.getXcmDeliveryFee(token, to);

return combineLatest({
txFee: this.estimateTxFee({
amount: FN.ZERO,
Expand All @@ -173,14 +179,14 @@ class BasePolkadotAdapter extends BaseCrossChainAdapter {
balance: this.balanceAdapter
.subscribeBalance(token, address)
.pipe(map((i) => i.available)),
deliveryFee: from(getPolkadotXcmDeliveryFee(this.chain.id, to, this.api)),
}).pipe(
map(({ balance, txFee, deliveryFee }) => {
map(({ balance, txFee }) => {
const tokenMeta = this.balanceAdapter?.getToken(token);
const feeFactor = 1.2;
const fee = FN.fromInner(txFee, tokenMeta?.decimals).mul(
new FN(feeFactor)
);
const deliveryFee = xcmDeliveryFee?.balance || FN.ZERO;

// always minus ed
return balance
Expand Down
45 changes: 32 additions & 13 deletions src/base-chain-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import {
isChainEqual,
validateAddress,
getDestAccountInfo,
getPolkadotXcmDeliveryFee,
} from "./utils";

const DEFAULT_TX_CHECKING_TIMEOUT = 2 * 60 * 1000;
Expand Down Expand Up @@ -97,6 +96,7 @@ export abstract class BaseCrossChainAdapter {
const { signer, to, token } = params;

const destFee = this.getCrossChainFee(token, to);
const xcmDeliveryFee = this.getXcmDeliveryFee(token, to);

// subscribe destination min receive
const minInput$ = this.subscribeMinInput(token, to);
Expand All @@ -108,18 +108,13 @@ export abstract class BaseCrossChainAdapter {
const fromApi = this.api as AnyApi;
const paymentToken = fromApi.registry.chainTokens[0];
const decimals = fromApi.registry.chainDecimals[0];
// TODO: only kusama and polkadot have it for now, refactor when other chains have this
const xcmDeliveryFee$ = ["polkadot", "kusama"].includes(this.chain.id)
? from(getPolkadotXcmDeliveryFee(this.chain.id, to, this.api))
: of(null);

return combineLatest({
minInput: minInput$,
maxInput: maxInput$,
estimateFee: estimateFee$,
xcmDeliveryFee: xcmDeliveryFee$,
}).pipe(
map(({ estimateFee, maxInput, minInput, xcmDeliveryFee }) => {
map(({ estimateFee, maxInput, minInput }) => {
return {
minInput: minInput.max(FN.ZERO),
maxInput: maxInput.max(FN.ZERO),
Expand All @@ -129,12 +124,7 @@ export abstract class BaseCrossChainAdapter {
token: paymentToken,
balance: FN.fromInner(estimateFee, decimals),
},
xcmFee: xcmDeliveryFee
? {
token: paymentToken,
balance: xcmDeliveryFee,
}
: null,
xcmFee: xcmDeliveryFee || null,
};
})
);
Expand Down Expand Up @@ -212,6 +202,35 @@ export abstract class BaseCrossChainAdapter {
};
}

public getXcmDeliveryFee(
token: string,
destChain: ChainId
): TokenBalance | null {
const router = this.routers.find(
(e) => e.to === destChain && e.token === token
);

if (!router) {
throw new RouterConfigNotFound(token, destChain, this.chain.id);
}

const deliveryFee = router.xcm?.deliveryFee;

if (!deliveryFee) {
return null;
}

const feeToken = deliveryFee?.token || token;

return {
token: feeToken,
balance: FN.fromInner(
deliveryFee?.amount || 0,
this.getToken(feeToken, destChain).decimals
).mul(new FN(1.1)),
};
}

public getDestWeight(
token: string,
destChain: ChainId
Expand Down
5 changes: 5 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ export interface XCMTransferConfigs {
token: string;
amount: string;
};
// XCM delivery fee charged by `from chain`
deliveryFee?: {
token: string;
amount: string;
};
}

export interface NetworkProps {
Expand Down
3 changes: 2 additions & 1 deletion src/utils/get-xcm-delivery-fee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import { ChainId, chains } from "../configs";

// refer to https://github.com/albertov19/xcmTools/blob/main/calculateKusamaDeliveryFees.ts
// delivery_fee_factor * (base_fee + encoded_msg_len * per_byte_fee)
// TODO: when most chains added xcm delivery fee, may move these to bridge package

/**
* Only for polkadot and kusama dmp for now
*
* FIXME: This is not accurate, need to get the real xcm message from client. Currently use the hardcoded value in each route config
*/
export async function getPolkadotXcmDeliveryFee(
from: ChainId,
Expand Down

0 comments on commit 3972b7b

Please sign in to comment.