Skip to content

Commit

Permalink
fix: bifrost xcm types (#1353)
Browse files Browse the repository at this point in the history
* fix: use dynamic xcm types for versions

* chore: fix comments
  • Loading branch information
Asmadek authored and stepanLav committed Jan 9, 2024
1 parent 19e33e2 commit 3b943e6
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 28 deletions.
8 changes: 0 additions & 8 deletions src/renderer/entities/network/lib/common/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { BN, BN_THOUSAND, BN_TWO } from '@polkadot/util';

export const enum Chains {
POLKADOT = '0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3',
KUSAMA = '0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe',
Expand All @@ -19,10 +17,4 @@ export const AUTO_BALANCE_TIMEOUT = 1000;
export const MAX_ATTEMPTS = 3;
export const PROGRESSION_BASE = 2;

// Some chains incorrectly use these, i.e. it is set to values such as 0 or even 2
// Use a low minimum validity threshold to check these against
export const THRESHOLD = BN_THOUSAND.div(BN_TWO);
export const DEFAULT_TIME = new BN(6_000);
export const ONE_DAY = new BN(24 * 60 * 60 * 1000);

export const GET_METADATA_METHOD = 'state_getMetadata';
6 changes: 5 additions & 1 deletion src/renderer/shared/api/xcm/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ export type XcmTransfer = {
};
};

export type XcmTransferType = 'xtokens' | 'xcmpallet' | 'xcmpallet-teleport';
export const enum XcmTransferType {
XTOKENS = 'xtokens',
XCMPALLET = 'xcmpallet',
XCMPALLET_TELEPORT = 'xcmpallet-teleport',
}
export type PathType = 'absolute' | 'relative' | 'concrete';

export const enum Action {
Expand Down
20 changes: 15 additions & 5 deletions src/renderer/shared/api/xcm/xcmService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ApiPromise } from '@polkadot/api';
import get from 'lodash/get';

import { XCM_URL, XCM_KEY } from './lib/constants';
import { getTypeVersion, toLocalChainId, getAssetId, TEST_ACCOUNT_ID } from '@shared/lib/utils';
import { getTypeVersion, toLocalChainId, getTypeName, getAssetId, TEST_ACCOUNT_ID } from '@shared/lib/utils';
import { XcmPalletTransferArgs, XTokenPalletTransferArgs } from '@entities/transaction';
import { chainsService } from '@entities/network';
import { toRawString } from './lib/utils';
Expand All @@ -20,6 +20,7 @@ import {
XcmTransfer,
PathType,
Action,
XcmTransferType,
} from './lib/types';

export const fetchXcmConfig = async (): Promise<XcmConfig> => {
Expand Down Expand Up @@ -199,6 +200,7 @@ export const createJunctionFromObject = (data: {}) => {

export const getAssetLocation = (
api: ApiPromise,
transferType: XcmTransferType,
asset: AssetXCM,
assets: Record<AssetName, AssetLocation>,
amount: BN,
Expand All @@ -212,7 +214,8 @@ export const getAssetLocation = (

const location = PathMap[asset.assetLocationPath.type]();

const assetVersionType = getTypeVersion(api, isArray ? 'XcmVersionedMultiAssets' : 'XcmVersionedMultiAsset');
const type = getTypeName(api, transferType, isArray ? 'assets' : 'asset');
const assetVersionType = getTypeVersion(api, type || '');
const assetObject = {
id: {
Concrete: location,
Expand Down Expand Up @@ -260,12 +263,14 @@ const getConcreteAssetLocation = (assetLocation?: LocalMultiLocation): Object |

export const getVersionedDestinationLocation = (
api: ApiPromise,
transferType: XcmTransferType,
originChain: Pick<Chain, 'parentId'>,
destinationParaId?: number,
accountId?: AccountId,
): Object | undefined => {
const location = getDestinationLocation(originChain, destinationParaId, accountId);
const version = getTypeVersion(api, 'XcmVersionedMultiLocation');
const type = getTypeName(api, transferType, 'dest');
const version = getTypeVersion(api, type || '');

if (!version) return location;

Expand Down Expand Up @@ -294,9 +299,14 @@ export const getDestinationLocation = (
return undefined;
};

export const getVersionedAccountLocation = (api: ApiPromise, accountId?: AccountId): Object | undefined => {
export const getVersionedAccountLocation = (
api: ApiPromise,
transferType: XcmTransferType,
accountId?: AccountId,
): Object | undefined => {
const location = getAccountLocation(accountId);
const version = getTypeVersion(api, 'XcmVersionedMultiLocation');
const type = getTypeName(api, transferType, 'dest');
const version = getTypeVersion(api, type || '');

if (!version) return location;

Expand Down
1 change: 1 addition & 0 deletions src/renderer/shared/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ export { RewardsDestination } from './types/stake';
export type { Stake, Unlocking } from './types/stake';

export type { ProxyAccount, PartialProxyAccount, ProxyType } from './types/proxy';
export { XcmPallets } from './types/substrate';
5 changes: 5 additions & 0 deletions src/renderer/shared/core/types/substrate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const enum XcmPallets {
XTOKENS = 'xTokens',
XCM_PALLET = 'xcmPallet',
POLKADOT_XCM = 'polkadotXcm',
}
2 changes: 1 addition & 1 deletion src/renderer/shared/lib/utils/__tests__/substrate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ApiPromise } from '@polkadot/api';
import { BN, BN_TWO } from '@polkadot/util';

import { getExpectedBlockTime } from '../substrate';
import { DEFAULT_TIME, THRESHOLD } from '@entities/network/lib/common/constants';
import { DEFAULT_TIME, THRESHOLD } from '../constants';

describe('shared/lib/utils/substrate', () => {
const blockTime = new BN(10_000);
Expand Down
8 changes: 8 additions & 0 deletions src/renderer/shared/lib/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { BN, BN_THOUSAND, BN_TWO } from '@polkadot/util';

export const ZERO_BALANCE = '0';

export const DEFAULT_TRANSITION = 300;
Expand Down Expand Up @@ -30,3 +32,9 @@ export const RootExplorers = [
{ name: 'Subscan', account: 'https://subscan.io/account/{address}' },
{ name: 'Sub.ID', account: 'https://sub.id/{address}' },
];

// Some chains incorrectly use these, i.e. it is set to values such as 0 or even 2
// Use a low minimum validity threshold to check these against
export const THRESHOLD = BN_THOUSAND.div(BN_TWO);
export const DEFAULT_TIME = new BN(6_000);
export const ONE_DAY = new BN(24 * 60 * 60 * 1000);
37 changes: 35 additions & 2 deletions src/renderer/shared/lib/utils/substrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { isHex, hexToU8a, bnMin, BN_TWO, BN } from '@polkadot/util';
import { blake2AsHex } from '@polkadot/util-crypto';
import { u32 } from '@polkadot/types';

import { Address, CallData, CallHash } from '@shared/core';
import { DEFAULT_TIME, ONE_DAY, THRESHOLD } from '@entities/network';
import { Address, CallData, CallHash, XcmPallets } from '@shared/core';
import { XcmTransferType } from '../../api/xcm';
import { DEFAULT_TIME, ONE_DAY, THRESHOLD } from './constants';

const V3_LABEL = 'V3';
const UNUSED_LABEL = 'unused';
Expand Down Expand Up @@ -135,3 +136,35 @@ export const getTypeVersions = (api: ApiPromise, typeName: string): string[] =>
// @ts-ignore
return api.createType(typeName).defKeys;
};

export const getTypeName = (api: ApiPromise, transferType: XcmTransferType, paramName: string): string | undefined => {
const { pallet, call } = getPalletAndCallByXcmTransferType(api, transferType);

const param = api.tx[pallet][call].meta.args.find((n) => n.name.toString() === paramName);

if (param) {
return param.type.toString();
}
};

export const getPalletAndCallByXcmTransferType = (
api: ApiPromise,
transferType: XcmTransferType,
): { pallet: XcmPallets; call: string } => {
if (transferType === XcmTransferType.XTOKENS) {
return { pallet: XcmPallets.XTOKENS, call: 'transferMultiasset' };
}

const pallet = api.tx.xcmPallet ? XcmPallets.XCM_PALLET : XcmPallets.POLKADOT_XCM;

if (transferType === XcmTransferType.XCMPALLET) {
return { pallet, call: 'limitedReserveTransferAssets' };
}

if (transferType === XcmTransferType.XCMPALLET_TELEPORT) {
return { pallet, call: 'limitedTeleportAssets' };
}

// Should never be reached as all transferType cases are covered
throw new Error('Invalid transferType');
};
19 changes: 10 additions & 9 deletions src/renderer/widgets/SendAssetModal/model/send-asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
getVersionedAccountLocation,
estimateRequiredDestWeight,
getVersionedDestinationLocation,
XcmTransferType,
} from '@shared/api/xcm';
import { xcmModel } from '@entities/xcm';
import { toLocalChainId, getParachainId } from '@shared/lib/utils';
Expand Down Expand Up @@ -147,9 +148,9 @@ sample({
if (!xcmTransfer || !chain || !api) return null;

return (
(xcmTransfer.type === 'xtokens' && accountId
? getVersionedDestinationLocation(api, chain, paraId || undefined, accountId)
: getVersionedDestinationLocation(api, chain, paraId || undefined)) || null
(xcmTransfer.type === XcmTransferType.XTOKENS && accountId
? getVersionedDestinationLocation(api, xcmTransfer.type, chain, paraId || undefined, accountId)
: getVersionedDestinationLocation(api, xcmTransfer.type, chain, paraId || undefined)) || null
);
},
target: $txDest,
Expand All @@ -161,11 +162,11 @@ sample({
});

sample({
source: { accountId: $accountId, props: $xcmProps },
fn: ({ accountId, props: { api } }) => {
if (!accountId || accountId === '0x00' || !api) return null;
source: { accountId: $accountId, props: $xcmProps, xcmTransfer: $xcmTransfer },
fn: ({ xcmTransfer, accountId, props: { api } }) => {
if (!accountId || accountId === '0x00' || !api || !xcmTransfer) return null;

return getVersionedAccountLocation(api, accountId) || null;
return getVersionedAccountLocation(api, xcmTransfer.type, accountId) || null;
},
target: $txBeneficiary,
});
Expand Down Expand Up @@ -208,9 +209,9 @@ sample({
if (!api || !xcmAsset || !config || !xcmTransfer) return null;

const resultAmount = new BN(amount || 0).add(new BN(xcmFee || 0));
const isArray = xcmTransfer.type !== 'xtokens';
const isArray = xcmTransfer.type !== XcmTransferType.XTOKENS;

return getAssetLocation(api, xcmAsset, config.assetsLocation, resultAmount, isArray) || null;
return getAssetLocation(api, xcmTransfer.type, xcmAsset, config.assetsLocation, resultAmount, isArray) || null;
},
target: $txAsset,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,11 @@ export const InitOperation = ({
};

const getXcmTransferType = (type: XcmTransferType): TransactionType => {
if (type === 'xtokens') {
if (type === XcmTransferType.XTOKENS) {
return TransactionType.XTOKENS_TRANSFER_MULTIASSET;
}

if (type === 'xcmpallet-teleport') {
if (type === XcmTransferType.XCMPALLET_TELEPORT) {
return api.tx.xcmPallet ? TransactionType.XCM_TELEPORT : TransactionType.POLKADOT_XCM_TELEPORT;
}

Expand Down

0 comments on commit 3b943e6

Please sign in to comment.