Skip to content

Commit

Permalink
feat: get-xcm-delivery-fee
Browse files Browse the repository at this point in the history
  • Loading branch information
qiweiii committed Feb 1, 2024
1 parent b7074ef commit f06c713
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 2 deletions.
7 changes: 5 additions & 2 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 "rxjs";
import { combineLatest, map, Observable, from } from "rxjs";

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

Expand Down Expand Up @@ -172,8 +173,9 @@ class BasePolkadotAdapter extends BaseCrossChainAdapter {
balance: this.balanceAdapter
.subscribeBalance(token, address)
.pipe(map((i) => i.available)),
deliveryFee: from(getPolkadotXcmDeleveryFee(this.chain.id, to, this.api)),
}).pipe(
map(({ balance, txFee }) => {
map(({ balance, txFee, deliveryFee }) => {
const tokenMeta = this.balanceAdapter?.getToken(token);
const feeFactor = 1.2;
const fee = FN.fromInner(txFee, tokenMeta?.decimals).mul(
Expand All @@ -183,6 +185,7 @@ class BasePolkadotAdapter extends BaseCrossChainAdapter {
// always minus ed
return balance
.minus(fee)
.minus(deliveryFee)
.minus(FN.fromInner(tokenMeta?.ed || "0", tokenMeta?.decimals));
})
);
Expand Down
119 changes: 119 additions & 0 deletions src/utils/get-xcm-delivery-fee.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { AnyApi, FixedPointNumber } from "@acala-network/sdk-core";
import { XcmVersionedXcm } from "@polkadot/types/lookup";
import { Codec, Observable } from "@polkadot/types/types";
import { firstValueFrom } from "rxjs";

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
*/
export async function getPolkadotXcmDeleveryFee(
from: ChainId,
to: ChainId,
fromApi?: AnyApi
) {
if (from !== "polkadot" && from !== "kusama") {
throw new Error("from chain must be polkadot or kusama");
}
if (!fromApi) return FixedPointNumber.ZERO;
const decimal = fromApi?.registry.chainDecimals[0];
const paraID = chains[to].paraChainId;

// https://github.com/polkadot-fellows/runtimes/blob/16635f6abda9c5fe4b62231d632ab6f6695b48f7/system-parachains/constants/src/polkadot.rs#L60C29-L60C43
// https://github.com/polkadot-fellows/runtimes/blob/16635f6abda9c5fe4b62231d632ab6f6695b48f7/system-parachains/constants/src/kusama.rs#L38
const UNITS =
from === "polkadot" ? BigInt(10000000000) : BigInt(1000000000000);
const QUID = UNITS / BigInt(30);
const CENTS = QUID / BigInt(100);
// const GRAND = QUID / BigInt(1000);
const MILLICENTS = CENTS / BigInt(1000);

const byteFee = BigInt(10) * MILLICENTS;
const baseDeliveryFee = BigInt(3) * CENTS;

const exampleXcm: XcmVersionedXcm = fromApi?.createType(
"XcmVersionedXcm",
exampleXcmMessage
) as any;
const xcmBytes = exampleXcm.toU8a();

const deliveryFeeFactor: Codec = await firstValueFrom(
fromApi?.query.dmp.deliveryFeeFactor(BigInt(paraID)) as Observable<Codec>
);

const convDeliveryFeeFactor =
BigInt(deliveryFeeFactor.toString()) / BigInt(10 ** 18);

const fee =
convDeliveryFeeFactor *
(baseDeliveryFee + BigInt(xcmBytes.length) * byteFee);

console.log(
fee,
FixedPointNumber.fromInner(fee.toString(), decimal)
.mul(new FixedPointNumber(1.2))
.toString()
);

return FixedPointNumber.fromInner(fee.toString(), decimal).mul(
new FixedPointNumber(1.2) // add some buffer
);
}

const exampleXcmMessage = {
V3: [
{
WithdrawAsset: [
{
assets: [
{
ConcreteFungible: {
id: "Here",
amount: "20000000000000",
},
},
],
effects: [
{
BuyExecution: {
fees: "0",
weight_limit: {
Unlimited: null,
},
},
},
{
DepositAsset: {
assets: "All",
dest: {
X1: {
Parachain: "2000",
},
},
},
},
{
DepositReserveAsset: {
assets: "All",
dest: {
X1: {
AccountId32: {
network: "Any",
id: "0x76c7e05b8ee00557f8f7e11f283aacd3bbee59c1d9fd588ebbe1b6c435fe504c",
},
},
},
effects: [],
},
},
],
},
],
},
],
};
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from "./xtokens-params";
export * from "./polkadot-xcm-params";
export * from "./create-route-configs";
export * from "./destination-utils";
export * from "./get-xcm-delivery-fee";

0 comments on commit f06c713

Please sign in to comment.