Skip to content

Commit

Permalink
fix: foreign asset multilocation as hex (#1605)
Browse files Browse the repository at this point in the history
  • Loading branch information
Imod7 authored Mar 3, 2025
1 parent 0ad81d1 commit e65ba2b
Show file tree
Hide file tree
Showing 10 changed files with 608 additions and 12 deletions.
20 changes: 20 additions & 0 deletions docs/src/openapi-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3051,6 +3051,24 @@ components:
type: boolean
description: Whether the asset metadata may be changed by a non Force origin. Note, that some runtimes may not have
support for isFrozen and if so the following will be returned `isFrozen does not exist for this runtime`
AssetMultiLocation:
oneOf:
- $ref: '#/components/schemas/AssetMultiLocationObject'
- $ref: '#/components/schemas/AssetMultiLocationHex'
AssetMultiLocationObject:
type: object
properties:
parents:
type: string
format: unsignedInteger
interior:
type: object
description: The multiLocation of the foreign asset as an object.
example: "{\"parents\":\"2\",\"interior\":{\"X1\":{\"GlobalConsensus\":\"Polkadot\"}}}"
AssetMultiLocationHex:
type: string
pattern: '^0x[0-9a-fA-F]+$'
description: The multiLocation of the foreign asset given as a hexadecimal value.
BalanceLock:
type: object
properties:
Expand Down Expand Up @@ -4342,6 +4360,8 @@ components:
PalletsForeignAssetsInfo:
type: object
properties:
multiLocation:
$ref: '#/components/schemas/AssetMultiLocation'
foreignAssetInfo:
$ref: '#/components/schemas/AssetInfo'
foreignAssetMetadata:
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/assetHubNextWestendControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const assetHubNextWestendControllers: ControllerConfig = {
'PalletsDispatchables',
'PalletsErrors',
'PalletsEvents',
'PalletsForeignAssets',
'PalletsNominationPools',
'PalletsOnGoingReferenda',
'PalletsStakingProgress',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/assetHubWestendControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const assetHubWestendControllers: ControllerConfig = {
'PalletsDispatchables',
'PalletsErrors',
'PalletsEvents',
'PalletsForeignAssets',
'PalletsPoolAssets',
'RuntimeCode',
'RuntimeMetadata',
Expand Down
53 changes: 52 additions & 1 deletion src/services/pallets/PalletsForeignAssetsService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ import { ApiPromise } from '@polkadot/api';

import { sanitizeNumbers } from '../../sanitize/sanitizeNumbers';
import { foreignAssetsMetadata } from '../test-helpers/mock/assets/mockAssetHubKusamaData';
import { foreignAssetsEntries } from '../test-helpers/mock/data/foreignAssetsEntries';
import { foreignAssetsMetadataWestendAH } from '../test-helpers/mock/assets/mockAssetHubWestendData';
import { foreignAssetsEntries, foreignAssetsEntriesWestendAH } from '../test-helpers/mock/data/foreignAssetsEntries';
import { mockAssetHubKusamaApi } from '../test-helpers/mock/mockAssetHubKusamaApi';
import { mockAssetHubWestendApi } from '../test-helpers/mock/mockAssetHubWestendApi';
import { blockHash523510 } from '../test-helpers/mock/mockBlock523510';
import { blockHash5236177 } from '../test-helpers/mock/mockBlock5236177';
import foreignAssetsResponse from '../test-helpers/responses/pallets/foreignAssetsResponse.json';
import { PalletsForeignAssetsService } from './PalletsForeignAssetsService';

const foreignAssetsEntriesAt = () => Promise.resolve().then(() => foreignAssetsEntries());
Expand Down Expand Up @@ -49,6 +53,14 @@ describe('PalletsForeignAssetsService', () => {
},
items: [
{
multiLocation: {
parents: '2',
interior: {
X1: {
GlobalConsensus: 'Polkadot',
},
},
},
foreignAssetInfo: {
owner: 'FxqimVubBRPqJ8kTwb3wL7G4q645hEkBEnXPyttLsTrFc5Q',
issuer: 'FxqimVubBRPqJ8kTwb3wL7G4q645hEkBEnXPyttLsTrFc5Q',
Expand All @@ -72,6 +84,19 @@ describe('PalletsForeignAssetsService', () => {
},
},
{
multiLocation: {
parents: '1',
interior: {
X2: [
{
Parachain: '2,125',
},
{
GeneralIndex: '0',
},
],
},
},
foreignAssetInfo: {
owner: 'FBeL7DiQ6JkoypYATheXhH3GQr5de2L3hL444TP6qQr3yA9',
issuer: 'FBeL7DiQ6JkoypYATheXhH3GQr5de2L3hL444TP6qQr3yA9',
Expand Down Expand Up @@ -103,3 +128,29 @@ describe('PalletsForeignAssetsService', () => {
});
});
});

const foreignAssetsEntriesAtWAH = () => Promise.resolve().then(() => foreignAssetsEntriesWestendAH());

const mockApiWAH = {
...mockAssetHubWestendApi,
query: {
foreignAssets: {
asset: {
entries: foreignAssetsEntriesAtWAH,
},
metadata: foreignAssetsMetadataWestendAH,
},
},
} as unknown as ApiPromise;

const palletsForeignAssetsServiceWAH = new PalletsForeignAssetsService(mockApiWAH);

describe('PalletsForeignAssetsService', () => {
describe('PalletsForeignAssetsService.fetchForeignAssets', () => {
it('Should return the correct response for Foreign Assets', async () => {
const response = await palletsForeignAssetsServiceWAH.fetchForeignAssets(blockHash5236177);

expect(sanitizeNumbers(response)).toStrictEqual(foreignAssetsResponse);
});
});
});
33 changes: 24 additions & 9 deletions src/services/pallets/PalletsForeignAssetsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { ApiPromise } from '@polkadot/api';
import { Option } from '@polkadot/types';
import { AssetMetadata, BlockHash } from '@polkadot/types/interfaces';
import { PalletAssetsAssetDetails, StagingXcmV3MultiLocation } from '@polkadot/types/lookup';
import { AnyJson } from '@polkadot/types-codec/types';
import { isHex } from '@polkadot/util';

import { IForeignAssetInfo, IForeignAssets } from '../../types/responses';
import { AbstractService } from '../AbstractService';
Expand Down Expand Up @@ -48,28 +50,41 @@ export class PalletsForeignAssetsService extends AbstractService {
* This variable will then be used as the key to get the corresponding metadata of the foreign asset.
*
* This is based on the logic implemented by marshacb in asset-transfer-api-registry
* https://github.com/paritytech/asset-transfer-api-registry/blob/main/src/createRegistry.ts#L193-L238
* https://github.com/paritytech/asset-transfer-api-registry/blob/main/src/fetchSystemParachainForeignAssetInfo.ts#L25L36
*/
for (const [assetStorageKeyData, assetInfo] of foreignAssetInfo) {
const foreignAssetData: [StagingXcmV3MultiLocation] = assetStorageKeyData.toHuman() as unknown as [
StagingXcmV3MultiLocation,
];
let foreignAssetData: [StagingXcmV3MultiLocation] | string = '';
if (isHex(assetStorageKeyData)) {
foreignAssetData = assetStorageKeyData;
} else {
foreignAssetData = assetStorageKeyData.toHuman() as unknown as [StagingXcmV3MultiLocation];
}

let multiLocation: string | AnyJson = '';
if (foreignAssetData) {
// remove any commas from multilocation key values e.g. Parachain: 2,125 -> Parachain: 2125
const foreignAssetMultiLocationStr = JSON.stringify(foreignAssetData[0]).replace(/(\d),/g, '$1');
let assetMetadata: AssetMetadata | {};
// Checking if the foreign asset data is an array or not because there is a case that the
// Multilocation is given as a hexadecimal value (see foreign assets in Westend Asset Hub).
if (Array.isArray(foreignAssetData)) {
multiLocation = foreignAssetData[0] as unknown as AnyJson;
// remove any commas from multilocation key values e.g. Parachain: 2,125 -> Parachain: 2125
const MultiLocationStr = JSON.stringify(foreignAssetData[0]).replace(/(\d),/g, '$1');

const assetMetadata = await api.query.foreignAssets.metadata<AssetMetadata>(
JSON.parse(foreignAssetMultiLocationStr),
);
assetMetadata = await api.query.foreignAssets.metadata<AssetMetadata>(JSON.parse(MultiLocationStr));
} else {
multiLocation = foreignAssetData;
assetMetadata = {};
}

if (assetInfo.isSome) {
items.push({
multiLocation,
foreignAssetInfo: assetInfo.unwrap(),
foreignAssetMetadata: assetMetadata,
});
} else {
items.push({
multiLocation,
foreignAssetInfo: {},
foreignAssetMetadata: assetMetadata,
});
Expand Down
Loading

0 comments on commit e65ba2b

Please sign in to comment.