Skip to content

Commit

Permalink
Fix WeightToFee function in MangataAdapter (#111)
Browse files Browse the repository at this point in the history
* Fix WeightToFee function in MangataAdapter

* Caculate unit by decimals

* Change chainData to chainConfig

* Fix mangata crossChainTransfer function

* Rename x2Params to interior

* Format code with .prettierrc
  • Loading branch information
imstar15 authored Dec 5, 2023
1 parent 36c4322 commit 1c93e9c
Show file tree
Hide file tree
Showing 14 changed files with 442 additions and 399 deletions.
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"tabWidth": 2,
"useTabs": false,
"trailingComma": "all",
"printWidth": 150
}
58 changes: 19 additions & 39 deletions packages/adapter/src/chains/mangata.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import _ from "lodash";
import BN from "bn.js";
import type { SubmittableExtrinsic, AddressOrPair } from "@polkadot/api/types";
import type { u32, u64, u128, Option } from "@polkadot/types";
import type { u32, u128, Option } from "@polkadot/types";
import type { WeightV2 } from "@polkadot/types/interfaces";
import type { HexString } from "@polkadot/util/types";
import type { KeyringPair } from "@polkadot/keyring/types";
import { Weight } from "@oak-network/config";
import { ChainAdapter } from "./chainAdapter";
import {
convertAbsoluteLocationToRelative,
getDerivativeAccountV2,
sendExtrinsic,
} from "../util";
import { WEIGHT_REF_TIME_PER_SECOND } from "../constants";
import { getDerivativeAccountV2, sendExtrinsic } from "../util";
import { WEIGHT_REF_TIME_PER_NANOS, WEIGHT_REF_TIME_PER_SECOND, WEIGHT_PROOF_SIZE_PER_MB } from "../constants";
import { SendExtrinsicResult } from "../types";

// MangataAdapter implements ChainAdapter
Expand All @@ -31,12 +27,8 @@ export class MangataAdapter extends ChainAdapter {
* @returns Extrinsic weight
*/
// eslint-disable-next-line class-methods-use-this
async getExtrinsicWeight(
extrinsic: SubmittableExtrinsic<"promise">,
account: AddressOrPair,
): Promise<Weight> {
const { refTime, proofSize } = (await extrinsic.paymentInfo(account))
.weight as unknown as WeightV2;
async getExtrinsicWeight(extrinsic: SubmittableExtrinsic<"promise">, account: AddressOrPair): Promise<Weight> {
const { refTime, proofSize } = (await extrinsic.paymentInfo(account)).weight as unknown as WeightV2;
return new Weight(new BN(refTime.unwrap()), new BN(proofSize.unwrap()));
}

Expand All @@ -46,15 +38,10 @@ export class MangataAdapter extends ChainAdapter {
* @param instructionCount The number of XCM instructions
* @returns XCM overall weight
*/
async calculateXcmOverallWeight(
transactCallWeight: Weight,
instructionCount: number,
): Promise<Weight> {
async calculateXcmOverallWeight(transactCallWeight: Weight, instructionCount: number): Promise<Weight> {
const { xcm } = this.chainConfig;
if (_.isUndefined(xcm)) throw new Error("chainConfig.xcm not set");
const overallWeight = transactCallWeight.add(
xcm.instructionWeight.muln(instructionCount),
);
const overallWeight = transactCallWeight.add(xcm.instructionWeight.muln(instructionCount));
return overallWeight;
}

Expand All @@ -66,24 +53,24 @@ export class MangataAdapter extends ChainAdapter {
*/
async weightToFee(weight: Weight, assetLocation: any): Promise<BN> {
const [defaultAsset] = this.chainConfig.assets;
if (_.isUndefined(defaultAsset))
throw new Error("chainConfig.defaultAsset not set");
if (_.isUndefined(defaultAsset)) throw new Error("chainConfig.defaultAsset not set");

const api = this.getApi();
if (_.isEqual(defaultAsset.location, assetLocation)) {
const fee = (await api.call.transactionPaymentApi.queryWeightToFee(
weight,
)) as u64;
return fee;
const unit = new BN(10).pow(new BN(defaultAsset.decimals));
// ExtrinsicBaseWeight benchmark value: 114756 nano seconds
const extrinsicBaseWeight = WEIGHT_REF_TIME_PER_NANOS.mul(new BN(114756));
const feePerSecond = WEIGHT_REF_TIME_PER_SECOND.div(extrinsicBaseWeight).mul(unit);
const refTimeFee = weight.refTime.mul(feePerSecond).div(WEIGHT_REF_TIME_PER_SECOND);
const proofSizeFee = weight.proofSize.mul(feePerSecond).div(WEIGHT_PROOF_SIZE_PER_MB);
return refTimeFee.add(proofSizeFee);
}
const storageValue =
await api.query.assetRegistry.locationToAssetId(assetLocation);
const storageValue = await api.query.assetRegistry.locationToAssetId(assetLocation);
const item = storageValue as unknown as Option<u32>;
if (item.isNone) throw new Error("AssetTypeUnitsPerSecond is null");

const assetId = item.unwrap();
const metadataStorageValue =
await api.query.assetRegistry.metadata(assetId);
const metadataStorageValue = await api.query.assetRegistry.metadata(assetId);
const metadataItem = metadataStorageValue as unknown as Option<any>;
if (metadataItem.isNone) throw new Error("Metadata is null");

Expand Down Expand Up @@ -137,25 +124,18 @@ export class MangataAdapter extends ChainAdapter {
const { key } = this.chainConfig;
if (_.isUndefined(key)) throw new Error("chainConfig.key not set");

const transferAssetLocation = this.isNativeAsset(assetLocation)
? convertAbsoluteLocationToRelative(assetLocation)
: assetLocation;

const api = this.getApi();
const extrinsic = api.tx.xTokens.transferMultiasset(
{
V3: {
fun: { Fungible: assetAmount },
id: { Concrete: transferAssetLocation },
id: { Concrete: assetLocation },
},
},
{
V3: {
interior: {
X2: [
destination.interior.X1,
{ AccountId32: { id: recipient, network: null } },
],
X2: [destination.interior.X1, { AccountId32: { id: recipient, network: null } }],
},
parents: 1,
},
Expand Down
57 changes: 15 additions & 42 deletions packages/adapter/src/chains/moonbeam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ import type { HexString } from "@polkadot/util/types";
import type { KeyringPair } from "@polkadot/keyring/types";
import { Weight } from "@oak-network/config";
import { ChainAdapter, TaskScheduler } from "./chainAdapter";
import {
convertAbsoluteLocationToRelative,
getDerivativeAccountV3,
sendExtrinsic,
} from "../util";
import { convertAbsoluteLocationToRelative, getDerivativeAccountV3, sendExtrinsic } from "../util";
import { AccountType, SendExtrinsicResult } from "../types";
import { WEIGHT_REF_TIME_PER_SECOND } from "../constants";

Expand All @@ -25,11 +21,11 @@ export class MoonbeamAdapter extends ChainAdapter implements TaskScheduler {
async initialize() {
// As of 12/02/2023, api.consts and api.query both return {} from all Moonriver endpoints.
// Maybe additional calls are required prior to fetch api.consts

// await this.fetchAndUpdateConfigs();

this.chainConfig.ss58Prefix = 1285;
this.chainConfig.paraId = 2023;
this.chainConfig.ss58Prefix = 1285;
this.chainConfig.paraId = 2023;
}

/**
Expand Down Expand Up @@ -74,12 +70,8 @@ export class MoonbeamAdapter extends ChainAdapter implements TaskScheduler {
* @returns Extrinsic weight
*/
// eslint-disable-next-line class-methods-use-this
async getExtrinsicWeight(
extrinsic: SubmittableExtrinsic<"promise">,
account: AddressOrPair,
): Promise<Weight> {
const { refTime, proofSize } = (await extrinsic.paymentInfo(account))
.weight as unknown as WeightV2;
async getExtrinsicWeight(extrinsic: SubmittableExtrinsic<"promise">, account: AddressOrPair): Promise<Weight> {
const { refTime, proofSize } = (await extrinsic.paymentInfo(account)).weight as unknown as WeightV2;
return new Weight(new BN(refTime.unwrap()), new BN(proofSize.unwrap()));
}

Expand All @@ -89,15 +81,10 @@ export class MoonbeamAdapter extends ChainAdapter implements TaskScheduler {
* @param instructionCount
* @returns XCM overall weight
*/
async calculateXcmOverallWeight(
transactCallWeight: Weight,
instructionCount: number,
): Promise<Weight> {
async calculateXcmOverallWeight(transactCallWeight: Weight, instructionCount: number): Promise<Weight> {
const { xcm } = this.chainConfig;
if (_.isUndefined(xcm)) throw new Error("chainConfig.xcm not set");
const overallWeight = transactCallWeight.add(
xcm.instructionWeight.muln(instructionCount),
);
const overallWeight = transactCallWeight.add(xcm.instructionWeight.muln(instructionCount));
return overallWeight;
}

Expand All @@ -109,13 +96,10 @@ export class MoonbeamAdapter extends ChainAdapter implements TaskScheduler {
*/
async weightToFee(weight: Weight, assetLocation: any): Promise<BN> {
const [defaultAsset] = this.chainConfig.assets;
if (_.isUndefined(defaultAsset))
throw new Error("chainConfig.defaultAsset not set");
if (_.isUndefined(defaultAsset)) throw new Error("chainConfig.defaultAsset not set");
const api = this.getApi();
if (_.isEqual(defaultAsset.location, assetLocation)) {
const fee = (await api.call.transactionPaymentApi.queryWeightToFee(
weight,
)) as u64;
const fee = (await api.call.transactionPaymentApi.queryWeightToFee(weight)) as u64;
return fee;
}
const storageValue = await api.query.assetManager.assetTypeUnitsPerSecond({
Expand Down Expand Up @@ -159,11 +143,8 @@ export class MoonbeamAdapter extends ChainAdapter implements TaskScheduler {
if (_.isUndefined(key)) throw new Error("chainConfig.key not set");

const [defaultAsset] = this.chainConfig.assets;
if (_.isUndefined(defaultAsset))
throw new Error("chainConfig.defaultAsset not set");
const currency = _.isEqual(feeLocation, defaultAsset.location)
? { AsCurrencyId: "SelfReserve" }
: { AsMultiLocation: { V3: feeLocation } };
if (_.isUndefined(defaultAsset)) throw new Error("chainConfig.defaultAsset not set");
const currency = _.isEqual(feeLocation, defaultAsset.location) ? { AsCurrencyId: "SelfReserve" } : { AsMultiLocation: { V3: feeLocation } };
const extrinsic = this.getApi().tx.xcmTransactor.transactThroughSigned(
{ V3: destination },
{ currency, feeAmount },
Expand All @@ -172,10 +153,7 @@ export class MoonbeamAdapter extends ChainAdapter implements TaskScheduler {
false,
);

console.log(
`Send extrinsic from ${key} to schedule task. extrinsic:`,
extrinsic.method.toHex(),
);
console.log(`Send extrinsic from ${key} to schedule task. extrinsic:`, extrinsic.method.toHex());
const result = await sendExtrinsic(api, extrinsic, keyringPair);
return result;
}
Expand Down Expand Up @@ -221,9 +199,7 @@ export class MoonbeamAdapter extends ChainAdapter implements TaskScheduler {
const { key } = this.chainConfig;
if (_.isUndefined(key)) throw new Error("chainConfig.key not set");

const transferAssetLocation = this.isNativeAsset(assetLocation)
? convertAbsoluteLocationToRelative(assetLocation)
: assetLocation;
const transferAssetLocation = this.isNativeAsset(assetLocation) ? convertAbsoluteLocationToRelative(assetLocation) : assetLocation;

const api = this.getApi();
const extrinsic = api.tx.xTokens.transferMultiasset(
Expand All @@ -236,10 +212,7 @@ export class MoonbeamAdapter extends ChainAdapter implements TaskScheduler {
{
V3: {
interior: {
X2: [
destination.interior.X1,
{ AccountId32: { id: recipient, network: null } },
],
X2: [destination.interior.X1, { AccountId32: { id: recipient, network: null } }],
},
parents: 1,
},
Expand Down
57 changes: 57 additions & 0 deletions packages/adapter/src/chains/oak.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ import { AccountType, SendExtrinsicResult } from "../types";
import { WEIGHT_REF_TIME_PER_SECOND } from "../constants";
import { InvalidAddress } from "../errors";

export interface AutomationPriceTriggerParams {
chain: string;
exchange: string;
asset1: string;
asset2: string;
submittedAt: number;
triggerFunction: "lt" | "gt";
triggerParam: number[];
}

export enum OakAdapterTransactType {
PayThroughRemoteDerivativeAccount,
PayThroughSoverignAccount,
Expand Down Expand Up @@ -235,6 +245,53 @@ export class OakAdapter extends ChainAdapter {
return result;
}

/**
* Schedule XCMP task
* @param destination The location of the destination chain
* @param schedule Schedule setting
* @param scheduleFee Schedule fee
* @param executionFee Execution fee
* @param encodedCall Encoded call
* @param encodedCallWeight The encoded call weight weight of the XCM instructions
* @param overallWeight The overall weight of the XCM instructions
* @param keyringPair Operator's keyring pair
* @returns SendExtrinsicResult
*/
async scheduleXcmpPriceTask(
automationPriceTriggerParams: AutomationPriceTriggerParams,
destination: any,
scheduleFee: any,
executionFee: any,
encodedCall: HexString,
encodedCallWeight: Weight,
overallWeight: Weight,
keyringPair: KeyringPair,
): Promise<SendExtrinsicResult> {
const api = this.getApi();
const { key } = this.chainConfig;
if (_.isUndefined(key)) throw new Error("chainData.key not set");

const extrinsic = api.tx.automationPrice.scheduleXcmpTask(
automationPriceTriggerParams.chain,
automationPriceTriggerParams.exchange,
automationPriceTriggerParams.asset1,
automationPriceTriggerParams.asset2,
automationPriceTriggerParams.submittedAt,
automationPriceTriggerParams.triggerFunction,
automationPriceTriggerParams.triggerParam,
destination,
scheduleFee,
executionFee,
encodedCall,
encodedCallWeight,
overallWeight,
);

console.log(`Send extrinsic from ${key} to schedule price task. extrinsic:`, extrinsic.method.toHex());
const result = await sendExtrinsic(api, extrinsic, keyringPair);
return result;
}

/**
* Calculate the derivative account ID of a certain account ID
* @param accountId
Expand Down
1 change: 1 addition & 0 deletions packages/adapter/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import BN from "bn.js";

export const WEIGHT_REF_TIME_PER_NANOS = new BN(1000);
export const WEIGHT_REF_TIME_PER_SECOND = new BN(1000000000000);
export const WEIGHT_PROOF_SIZE_PER_MB = new BN(1024 * 1024);
Loading

0 comments on commit 1c93e9c

Please sign in to comment.