Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: xcm fees #117

Merged
merged 2 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading