@polkadot/types/interfaces#ParaId TypeScript Examples

The following examples show how to use @polkadot/types/interfaces#ParaId. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: useFunds.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
export default function useFunds (): Result {
  const { api } = useApi();
  const bestNumber = useBestNumber();
  const [paraIds, setParaIds] = useState<ParaId[]>([]);
  const trigger = useEventTrigger([api.events.crowdloan.Created]);
  const optFunds = useCallMulti<Option<FundInfo>[]>(paraIds.map((id) => [api.query.crowdloan.funds, id]));
  const [result, setResult] = useState<Result>(EMPTY);

  // we actually want to split this further info completed and ongoing
  const campaigns = useMemo(
    () => extractCampaigns(optFunds, paraIds),
    [optFunds, paraIds]
  );

  // on event triggers, update the available paraIds
  useEffect((): void => {
    trigger &&
      api.query.crowdloan.funds
        .keys<[ParaId]>()
        .then((indexes) => setParaIds(
          indexes.map(({ args: [paraId] }) => paraId))
        )
        .catch(console.error);
  }, [api, trigger]);

  // here we manually add the actual ending status and calculate the totals
  useEffect((): void => {
    bestNumber && campaigns && setResult((prev) =>
      createResult(bestNumber, campaigns, prev)
    );
  }, [bestNumber, campaigns]);

  return result;
}
Example #2
Source File: Parachains.tsx    From crust-apps with Apache License 2.0 6 votes vote down vote up
function mapValidators (ids?: ParaId[], validators?: AccountId[] | null, validatorGroups?: ParaValidatorIndex[][] | null): AccountId[][] {
  return validators && validatorGroups && ids && ids.length === validatorGroups.length
    ? validatorGroups.map((ids) =>
      ids
        .map((id) => validators[id.toNumber()])
        .filter((a) => a)
    )
    : [];
}
Example #3
Source File: index.tsx    From crust-apps with Apache License 2.0 6 votes vote down vote up
function Overview ({ className, proposals }: Props): React.ReactElement<Props> {
  const { api } = useApi();
  const paraIds = useCall<ParaId[]>(api.query.paras?.parachains);
  const actionsQueue = useActionsQueue();
  const leasePeriod = useLeasePeriod();
  const upcomingIds = useUpcomingIds();

  return (
    <div className={className}>
      <Summary
        leasePeriod={leasePeriod}
        parachainCount={paraIds?.length}
        proposalCount={proposals?.proposalIds.length}
        upcomingCount={upcomingIds?.length}
      />
      <Actions />
      {api.query.paras && (
        <>
          <Parachains
            actionsQueue={actionsQueue}
            ids={paraIds}
            scheduled={proposals?.scheduled}
          />
          <Upcomings
            actionsQueue={actionsQueue}
            currentPeriod={leasePeriod && leasePeriod.currentPeriod}
            ids={upcomingIds}
          />
        </>
      )}
    </div>
  );
}
Example #4
Source File: useActionsQueue.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
export default function useActionsQueue (): QueuedAction[] {
  const { api } = useApi();
  const currentIndex = useCall<SessionIndex>(api.query.session.currentIndex);
  const nextActions = useCallMulti<ParaId[][]>(
    currentIndex
      ? INC.map((inc) => [api.query.paras.actionsQueue, currentIndex.add(inc)])
      : []
  );

  return useMemo(
    (): QueuedAction[] =>
      currentIndex && nextActions
        ? nextActions.filter((paraIds) => paraIds.length).map((paraIds, index) => ({
          paraIds,
          sessionIndex: currentIndex.add(INC[index])
        }))
        : [],
    [currentIndex, nextActions]
  );
}
Example #5
Source File: useUpcomingIds.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
export default function useUpomingIds (): ParaId[] | undefined {
  const { api } = useApi();
  const trigger = useEventTrigger([api.events.session.NewSession, api.events.registrar?.Registered]);
  const [result, setResult] = useState<ParaId[] | undefined>();

  useEffect((): void => {
    trigger &&
      api.query.paras.paraLifecycles
        .entries<Option<ParaLifecycle>, [ParaId]>()
        .then((entries) => setResult(() =>
          entries
            .map(([{ args: [paraId] }, optValue]): ParaId | null => {
              const value = optValue.unwrap();

              return value && (
                value.isParathread ||
                value.isUpgradingToParachain ||
                value.isOutgoingParathread ||
                value.isOnboarding
              )
                ? paraId
                : null;
            })
            .filter((paraId): paraId is ParaId => !!paraId)
            .sort((a, b) => a.cmp(b))
        ))
        .catch(console.error);
  }, [api, trigger]);

  return result;
}
Example #6
Source File: useProposal.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
export default function useProposal (id: ParaId, approvedIds: ParaId[], scheduled: ScheduledProposals[]): ProposalExt {
  const { api } = useApi();
  const opt = useCall<Option<ParachainProposal>>(api.query.proposeParachain.proposals, [id]);

  return useMemo(
    (): ProposalExt => ({
      id,
      isApproved: approvedIds.some((a) => a.eq(id)),
      isScheduled: scheduled.some(({ scheduledIds }) => scheduledIds.some((s) => s.eq(id))),
      proposal: opt && opt.isSome
        ? opt.unwrap()
        : undefined
    }),
    [approvedIds, id, opt, scheduled]
  );
}
Example #7
Source File: useOwnedIds.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
export default function useOwnedIds (): OwnedId[] {
  const { api } = useApi();
  const { allAccounts } = useAccounts();
  const trigger = useEventTrigger([api.events.registrar?.Registered]);
  const [state, setState] = useState<OwnedId[]>([]);

  useEffect((): void => {
    allAccounts && trigger &&
      api.query.registrar?.paras
        .entries<Option<ParaInfo>, [ParaId]>()
        .then((entries) => setState(() =>
          entries
            .map(([{ args: [paraId] }, optInfo]): OwnedId | null => {
              if (optInfo.isNone) {
                return null;
              }

              const paraInfo = optInfo.unwrap();

              return {
                manager: paraInfo.manager.toString(),
                paraId,
                paraInfo
              };
            })
            .filter((info): info is OwnedId => !!info && allAccounts.some((a) => a === info.manager))
        ))
        .catch(console.error);
  }, [allAccounts, api, trigger]);

  return state;
}
Example #8
Source File: useProposals.ts    From crust-apps with Apache License 2.0 6 votes vote down vote up
function createResult (sessionIndex: SessionIndex, approvedIds: ParaId[], proposalKeys: { args: [ParaId] }[], scheduledProposals: [{ args: [SessionIndex] }, ParaId[]][]): Proposals {
  return {
    approvedIds,
    proposalIds: proposalKeys.map(({ args: [id] }) => id),
    scheduled: scheduledProposals
      .map(([{ args: [sessionIndex] }, scheduledIds]) => ({
        scheduledIds,
        sessionIndex
      }))
      .filter((s) => s.sessionIndex.gt(sessionIndex))
  };
}
Example #9
Source File: useFunds.ts    From crust-apps with Apache License 2.0 5 votes vote down vote up
// extract fund info from the available paraIds
function extractCampaigns (optFunds: Option<FundInfo>[], paraIds: ParaId[]): Campaign[] | null {
  return optFunds && paraIds.length === optFunds.length
    ? paraIds
      .map((paraId, i) => ({ info: optFunds[i].unwrapOr(null), key: paraId.toString(), paraId }))
      .filter((fund): fund is Campaign => !!fund.info)
    : null;
}
Example #10
Source File: Parachains.tsx    From crust-apps with Apache License 2.0 5 votes vote down vote up
function extractActions (actionsQueue: QueuedAction[], knownIds?: [ParaId, string][]): Record<string, QueuedAction | undefined> {
  return actionsQueue && knownIds
    ? knownIds.reduce((all: Record<string, QueuedAction | undefined>, [id, key]) => ({
      ...all,
      [key]: actionsQueue.find(({ paraIds }) => paraIds.some((p) => p.eq(id)))
    }), {})
    : {};
}
Example #11
Source File: Parachains.tsx    From crust-apps with Apache License 2.0 5 votes vote down vote up
function Parachains ({ actionsQueue, ids, scheduled }: Props): React.ReactElement<Props> {
  const { t } = useTranslation();
  const { api } = useApi();
  const bestNumber = useBestNumber();
  const lastBlock = useCall<SignedBlockExtended>(api.derive.chain.subscribeNewBlocks);
  const [{ lastBacked, lastIncluded, lastTimeout }, setLastEvents] = useState<LastEvents>(EMPTY_EVENTS);
  const [validators, validatorGroups] = useCallMulti<[AccountId[] | null, ParaValidatorIndex[][] | null]>([
    api.query.session?.validators,
    api.query.paraScheduler?.validatorGroups || api.query.scheduler?.validatorGroups
  ], optionsMulti);

  const headerRef = useRef([
    [t('parachains'), 'start', 2],
    ['', 'media--1500'],
    [t('head'), 'start'],
    [t('lifecycle'), 'start media--1100'],
    [],
    [t('included'), undefined, 2],
    [t('backed'), 'no-pad-left'],
    [t('timeout'), 'no-pad-left'],
    [t('chain best'), 'media--900 no-pad-left'],
    [t('upgrade'), 'media--1300'],
    [t('ump/dmp/hrmp'), 'media--1200']
  ]);

  const scheduledIds = useMemo(
    () => extractScheduledIds(scheduled),
    [scheduled]
  );

  const validatorMap = useMemo(
    () => mapValidators(ids, validators, validatorGroups),
    [ids, validators, validatorGroups]
  );

  const knownIds = useMemo(
    () => ids?.map((id): [ParaId, string] => [id, id.toString()]),
    [ids]
  );

  const nextActions = useMemo(
    () => extractActions(actionsQueue, knownIds),
    [actionsQueue, knownIds]
  );

  useEffect((): void => {
    lastBlock && setLastEvents((prev) =>
      extractEvents(api, lastBlock, prev)
    );
  }, [api, lastBlock]);

  return (
    <Table
      empty={knownIds && t<string>('There are no registered parachains')}
      header={headerRef.current}
    >
      {knownIds?.map(([id, key], index): React.ReactNode => (
        <Parachain
          bestNumber={bestNumber}
          id={id}
          isScheduled={scheduledIds[key]}
          key={key}
          lastBacked={lastBacked[key]}
          lastInclusion={lastIncluded[key]}
          lastTimeout={lastTimeout[key]}
          nextAction={nextActions[key]}
          sessionValidators={validators}
          validators={validatorMap[index]}
        />
      ))}
    </Table>
  );
}
Example #12
Source File: useTeleport.ts    From subscan-multisig-react with Apache License 2.0 5 votes vote down vote up
export function useTeleport(): Teleport {
  const { api, apiUrl, isApiReady } = useApi();
  const paraId = useCall<ParaId>(isApiReady && api.query.parachainInfo?.parachainId);
  const [state, setState] = useState<Teleport>(() => ({ ...DEFAULT_STATE }));

  useEffect((): void => {
    if (isApiReady) {
      const relayGenesis = api.genesisHash.toHex();
      const endpoint = endpoints.find(({ genesisHash }: any) => genesisHash === relayGenesis);

      if (endpoint) {
        const destinations = extractRelayDestinations(
          relayGenesis,
          ({ paraId }: any) => isNumber(paraId) && endpoint.teleport.includes(paraId)
        );
        const oneWay = extractRelayDestinations(
          relayGenesis,
          ({ paraId, teleport }: any) => isNumber(paraId) && !teleport.includes(-1)
        ).map(({ paraId }: any) => paraId || -1);

        setState({
          allowTeleport: destinations.length !== 0,
          destinations,
          isRelayTeleport: true,
          oneWay,
        });
      }
    }
  }, [api, isApiReady]);

  useEffect((): void => {
    if (paraId) {
      const endpoint = endpoints.find(({ value }: any) => value === apiUrl);

      if (endpoint && endpoint.genesisHashRelay) {
        const destinations = extractRelayDestinations(endpoint.genesisHashRelay, ({ paraId }: any) =>
          endpoint.teleport.includes(isNumber(paraId) ? paraId : -1)
        );
        const oneWay = extractRelayDestinations(
          endpoint.genesisHashRelay,
          ({ paraId, teleport }: any) => !teleport.includes(isNumber(paraId) ? paraId : -1)
        ).map(({ paraId }: any) => paraId || -1);

        setState({
          allowTeleport: destinations.length !== 0,
          destinations,
          isParaTeleport: true,
          oneWay,
        });
      }
    }
  }, [apiUrl, paraId]);

  return state;
}
Example #13
Source File: test-mock-hrmp.ts    From moonbeam with GNU General Public License v3.0 4 votes vote down vote up
describeDevMoonbeam("Mock XCM - receive horizontal transfer of DEV", (context) => {
  let alith: KeyringPair;
  let random: KeyringPair;
  let paraId: ParaId;
  let transferredBalance;
  let sovereignAddress;

  before("Should send DEV to the parachain sovereign", async function () {
    const keyringEth = new Keyring({ type: "ethereum" });
    alith = keyringEth.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
    random = keyringEth.addFromUri(RANDOM_PRIV_KEY, null, "ethereum");

    paraId = context.polkadotApi.createType("ParaId", 2000) as any;
    sovereignAddress = u8aToHex(
      new Uint8Array([...new TextEncoder().encode("sibl"), ...paraId.toU8a()])
    ).padEnd(42, "0");

    transferredBalance = 100000000000000n;

    // We first fund parachain 2000 sovreign account
    await createBlockWithExtrinsic(
      context,
      alith,
      context.polkadotApi.tx.balances.transfer(sovereignAddress, transferredBalance)
    );
    let balance = (
      (await context.polkadotApi.query.system.account(sovereignAddress)) as any
    ).data.free.toBigInt();
    expect(balance).to.eq(transferredBalance);
  });

  it("Should NOT receive MOVR from para Id 2000 with old reanchor", async function () {
    let ownParaId = (await context.polkadotApi.query.parachainInfo.parachainId()) as any;
    // Get Pallet balances index
    const metadata = await context.polkadotApi.rpc.state.getMetadata();
    const balancesPalletIndex = (metadata.asLatest.toHuman().pallets as Array<any>).find(
      (pallet) => {
        return pallet.name === "Balances";
      }
    ).index;
    // We are charging 100_000_000 weight for every XCM instruction
    // We are executing 4 instructions
    // 100_000_000 * 4 * 50000 = 20000000000000
    // We are charging 20 micro DEV for this operation
    // The rest should be going to the deposit account
    let xcmMessage = {
      V2: [
        {
          WithdrawAsset: [
            {
              id: {
                Concrete: {
                  parents: 1,
                  interior: {
                    X2: [{ Parachain: ownParaId }, { PalletInstance: balancesPalletIndex }],
                  },
                },
              },
              fun: { Fungible: transferredBalance },
            },
          ],
        },
        { ClearOrigin: null },
        {
          BuyExecution: {
            fees: {
              id: {
                Concrete: {
                  parents: 1,
                  interior: {
                    X2: [{ Parachain: ownParaId }, { PalletInstance: balancesPalletIndex }],
                  },
                },
              },
              fun: { Fungible: transferredBalance },
            },
            weightLimit: { Limited: new BN(4000000000) },
          },
        },
        {
          DepositAsset: {
            assets: { Wild: "All" },
            maxAssets: new BN(1),
            beneficiary: {
              parents: 0,
              interior: { X1: { AccountKey20: { network: "Any", key: random.address } } },
            },
          },
        },
      ],
    };
    const xcmpFormat: XcmpMessageFormat = context.polkadotApi.createType(
      "XcmpMessageFormat",
      "ConcatenatedVersionedXcm"
    ) as any;
    const receivedMessage: XcmVersionedXcm = context.polkadotApi.createType(
      "XcmVersionedXcm",
      xcmMessage
    ) as any;

    const totalMessage = [...xcmpFormat.toU8a(), ...receivedMessage.toU8a()];

    // Send RPC call to inject XCM message
    // We will set a specific message knowing that it should mint the statemint asset
    await customWeb3Request(context.web3, "xcm_injectHrmpMessage", [2000, totalMessage]);

    // Create a block in which the XCM will be executed
    await context.createBlock();

    // The message should not have been succesfully executed, since old prefix is not supported
    // anymore
    let balance = (
      (await context.polkadotApi.query.system.account(sovereignAddress)) as any
    ).data.free.toBigInt();
    expect(balance.toString()).to.eq(transferredBalance.toString());

    // the random address does not receive anything
    let randomBalance = (
      (await context.polkadotApi.query.system.account(random.address)) as any
    ).data.free.toBigInt();
    expect(randomBalance).to.eq(0n);
  });
});
Example #14
Source File: test-mock-hrmp.ts    From moonbeam with GNU General Public License v3.0 4 votes vote down vote up
describeDevMoonbeam(
  "Mock XCM - receive horizontal transfer of DEV with new reanchor",
  (context) => {
    let alith: KeyringPair;
    let random: KeyringPair;
    let paraId: ParaId;
    let transferredBalance;
    let sovereignAddress;

    before("Should send DEV to the parachain sovereign", async function () {
      const keyringEth = new Keyring({ type: "ethereum" });
      alith = keyringEth.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
      random = keyringEth.addFromUri(RANDOM_PRIV_KEY, null, "ethereum");

      paraId = context.polkadotApi.createType("ParaId", 2000) as any;
      sovereignAddress = u8aToHex(
        new Uint8Array([...new TextEncoder().encode("sibl"), ...paraId.toU8a()])
      ).padEnd(42, "0");

      transferredBalance = 100000000000000n;

      // We first fund parachain 2000 sovreign account
      await createBlockWithExtrinsic(
        context,
        alith,
        context.polkadotApi.tx.balances.transfer(sovereignAddress, transferredBalance)
      );
      let balance = (
        (await context.polkadotApi.query.system.account(sovereignAddress)) as any
      ).data.free.toBigInt();
      expect(balance).to.eq(transferredBalance);
    });

    it("Should receive MOVR from para Id 2000 with new reanchor logic", async function () {
      let ownParaId = (await context.polkadotApi.query.parachainInfo.parachainId()) as any;
      // Get Pallet balances index
      const metadata = await context.polkadotApi.rpc.state.getMetadata();
      const balancesPalletIndex = (metadata.asLatest.toHuman().pallets as Array<any>).find(
        (pallet) => {
          return pallet.name === "Balances";
        }
      ).index;
      // We are charging 100_000_000 weight for every XCM instruction
      // We are executing 4 instructions
      // 100_000_000 * 4 * 50000 = 20000000000000
      // We are charging 20 micro DEV for this operation
      // The rest should be going to the deposit account
      let xcmMessage = {
        V2: [
          {
            WithdrawAsset: [
              {
                // This is the new reanchored logic
                id: {
                  Concrete: {
                    parents: 0,
                    interior: {
                      X1: { PalletInstance: balancesPalletIndex },
                    },
                  },
                },
                fun: { Fungible: transferredBalance },
              },
            ],
          },
          { ClearOrigin: null },
          {
            BuyExecution: {
              fees: {
                id: {
                  // This is the new reanchored logic
                  Concrete: {
                    parents: 0,
                    interior: {
                      X1: { PalletInstance: balancesPalletIndex },
                    },
                  },
                },
                fun: { Fungible: transferredBalance },
              },
              weightLimit: { Limited: new BN(4000000000) },
            },
          },
          {
            DepositAsset: {
              assets: { Wild: "All" },
              maxAssets: new BN(1),
              beneficiary: {
                parents: 0,
                interior: { X1: { AccountKey20: { network: "Any", key: random.address } } },
              },
            },
          },
        ],
      };
      const xcmpFormat: XcmpMessageFormat = context.polkadotApi.createType(
        "XcmpMessageFormat",
        "ConcatenatedVersionedXcm"
      ) as any;
      const receivedMessage: XcmVersionedXcm = context.polkadotApi.createType(
        "XcmVersionedXcm",
        xcmMessage
      ) as any;

      const totalMessage = [...xcmpFormat.toU8a(), ...receivedMessage.toU8a()];

      // Send RPC call to inject XCM message
      // We will set a specific message knowing that it should mint the statemint asset
      await customWeb3Request(context.web3, "xcm_injectHrmpMessage", [2000, totalMessage]);

      // Create a block in which the XCM will be executed
      await context.createBlock();

      // We should expect sovereign balance to be 0, since we have transferred the full amount
      let balance = (
        (await context.polkadotApi.query.system.account(sovereignAddress)) as any
      ).data.free.toBigInt();
      expect(balance.toString()).to.eq(0n.toString());

      // In the case of the random address: we have transferred 100000000000000,
      // but 20000000000000 have been deducted
      // for weight payment
      let randomBalance = (
        (await context.polkadotApi.query.system.account(random.address)) as any
      ).data.free.toBigInt();
      let expectedRandomBalance = 80000000000000n;
      expect(randomBalance).to.eq(expectedRandomBalance);
    });
  }
);
Example #15
Source File: test-mock-hrmp.ts    From moonbeam with GNU General Public License v3.0 4 votes vote down vote up
describeDevMoonbeam("Mock XCM - receive horizontal transfer", (context) => {
  let assetId: string;
  let alith: KeyringPair;
  let baltathar: KeyringPair;
  let paraId: ParaId;
  let transferredBalance;
  let sovereignAddress;

  before("Should Register an asset and set unit per sec", async function () {
    const keyringEth = new Keyring({ type: "ethereum" });
    alith = keyringEth.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
    baltathar = await keyringEth.addFromUri(BALTATHAR_PRIVATE_KEY, null, "ethereum");

    // registerAsset
    const { events: eventsRegister } = await createBlockWithExtrinsic(
      context,
      alith,
      context.polkadotApi.tx.sudo.sudo(
        context.polkadotApi.tx.assetManager.registerLocalAsset(
          baltathar.address,
          baltathar.address,
          true,
          new BN(1)
        )
      )
    );

    // Look for assetId in events
    eventsRegister.forEach((e) => {
      if (e.section.toString() === "assetManager") {
        assetId = e.data[0].toHex();
      }
    });
    assetId = assetId.replace(/,/g, "");

    transferredBalance = new BN(100000000000000);

    // mint asset
    await createBlockWithExtrinsic(
      context,
      baltathar,
      context.polkadotApi.tx.localAssets.mint(assetId, alith.address, transferredBalance)
    );

    paraId = context.polkadotApi.createType("ParaId", 2000) as any;
    sovereignAddress = u8aToHex(
      new Uint8Array([...new TextEncoder().encode("sibl"), ...paraId.toU8a()])
    ).padEnd(42, "0");

    // We first fund parachain 2000 sovreign account
    await createBlockWithExtrinsic(
      context,
      alith,
      context.polkadotApi.tx.balances.transfer(sovereignAddress, transferredBalance)
    );

    // transfer to para Id sovereign to emulate having sent the tokens
    await createBlockWithExtrinsic(
      context,
      alith,
      context.polkadotApi.tx.localAssets.transfer(assetId, sovereignAddress, transferredBalance)
    );
  });

  it("Should receive 10 Local Asset tokens and sufficent DEV to pay for fee", async function () {
    const metadata = await context.polkadotApi.rpc.state.getMetadata();
    const balancesPalletIndex = (metadata.asLatest.toHuman().pallets as Array<any>).find(
      (pallet) => {
        return pallet.name === "Balances";
      }
    ).index;

    const localAssetsPalletIndex = (metadata.asLatest.toHuman().pallets as Array<any>).find(
      (pallet) => {
        return pallet.name === "LocalAssets";
      }
    ).index;

    // We are charging 100_000_000 weight for every XCM instruction
    // We are executing 4 instructions
    // 100_000_000 * 4 * 50000 = 20000000000000
    // We are charging 20 micro DEV for this operation
    // The rest should be going to the deposit account
    let xcmMessage = {
      V2: [
        {
          WithdrawAsset: [
            {
              // This is the new reanchored logic
              id: {
                Concrete: {
                  parents: 0,
                  interior: {
                    X1: { PalletInstance: balancesPalletIndex },
                  },
                },
              },
              fun: { Fungible: transferredBalance },
            },
            {
              // This is the new reanchored logic
              id: {
                Concrete: {
                  parents: 0,
                  interior: {
                    X2: [{ PalletInstance: localAssetsPalletIndex }, { GeneralIndex: assetId }],
                  },
                },
              },
              fun: { Fungible: transferredBalance },
            },
          ],
        },
        { ClearOrigin: null },
        {
          BuyExecution: {
            fees: {
              id: {
                // This is the new reanchored logic
                Concrete: {
                  parents: 0,
                  interior: {
                    X1: { PalletInstance: balancesPalletIndex },
                  },
                },
              },
              fun: { Fungible: transferredBalance },
            },
            weightLimit: { Limited: new BN(4000000000) },
          },
        },
        {
          DepositAsset: {
            assets: { Wild: "All" },
            maxAssets: new BN(2),
            beneficiary: {
              parents: 0,
              interior: { X1: { AccountKey20: { network: "Any", key: alith.address } } },
            },
          },
        },
      ],
    };

    const xcmpFormat: XcmpMessageFormat = context.polkadotApi.createType(
      "XcmpMessageFormat",
      "ConcatenatedVersionedXcm"
    ) as any;
    const receivedMessage: XcmVersionedXcm = context.polkadotApi.createType(
      "XcmVersionedXcm",
      xcmMessage
    ) as any;

    const totalMessage = [...xcmpFormat.toU8a(), ...receivedMessage.toU8a()];

    // Send RPC call to inject XCM message
    // We will set a specific message knowing that it should mint the statemint asset
    await customWeb3Request(context.web3, "xcm_injectHrmpMessage", [foreign_para_id, totalMessage]);

    // Create a block in which the XCM will be executed
    await context.createBlock();

    // Make sure the state has ALITH's LOCAL parachain tokens
    let alithLocalTokBalance = (
      (await context.polkadotApi.query.localAssets.account(assetId, alith.address)) as any
    )
      .unwrap()
      ["balance"].toBigInt();

    expect(alithLocalTokBalance.toString()).to.eq(transferredBalance.toString());
  });
});
Example #16
Source File: test-mock-hrmp.ts    From moonbeam with GNU General Public License v3.0 4 votes vote down vote up
describeDevMoonbeam("Mock XCM - receive horizontal transfer", (context) => {
  let assetId: string;
  let alith: KeyringPair;
  let baltathar: KeyringPair;
  let paraId: ParaId;
  let transferredBalance;
  let sovereignAddress;

  before("Should Register an asset and set unit per sec", async function () {
    const keyringEth = new Keyring({ type: "ethereum" });
    alith = keyringEth.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
    baltathar = await keyringEth.addFromUri(BALTATHAR_PRIVATE_KEY, null, "ethereum");

    // registerAsset
    const { events: eventsRegister } = await createBlockWithExtrinsic(
      context,
      alith,
      context.polkadotApi.tx.sudo.sudo(
        context.polkadotApi.tx.assetManager.registerLocalAsset(
          baltathar.address,
          baltathar.address,
          true,
          new BN(1)
        )
      )
    );

    // Look for assetId in events
    eventsRegister.forEach((e) => {
      if (e.section.toString() === "assetManager") {
        assetId = e.data[0].toHex();
      }
    });
    assetId = assetId.replace(/,/g, "");

    transferredBalance = new BN(100000000000000);

    // mint asset
    await createBlockWithExtrinsic(
      context,
      baltathar,
      context.polkadotApi.tx.localAssets.mint(assetId, alith.address, transferredBalance)
    );

    paraId = context.polkadotApi.createType("ParaId", 2000) as any;
    sovereignAddress = u8aToHex(
      new Uint8Array([...new TextEncoder().encode("sibl"), ...paraId.toU8a()])
    ).padEnd(42, "0");

    // We first fund parachain 2000 sovreign account
    await createBlockWithExtrinsic(
      context,
      alith,
      context.polkadotApi.tx.balances.transfer(sovereignAddress, transferredBalance)
    );

    // transfer to para Id sovereign to emulate having sent the tokens
    await createBlockWithExtrinsic(
      context,
      alith,
      context.polkadotApi.tx.localAssets.transfer(assetId, sovereignAddress, transferredBalance)
    );
  });

  it("Should NOT receive 10 Local Assets and DEV for fee with old reanchor", async function () {
    let ownParaId = (await context.polkadotApi.query.parachainInfo.parachainId()) as any;
    const metadata = await context.polkadotApi.rpc.state.getMetadata();
    const balancesPalletIndex = (metadata.asLatest.toHuman().pallets as Array<any>).find(
      (pallet) => {
        return pallet.name === "Balances";
      }
    ).index;

    const localAssetsPalletIndex = (metadata.asLatest.toHuman().pallets as Array<any>).find(
      (pallet) => {
        return pallet.name === "LocalAssets";
      }
    ).index;

    // We are charging 100_000_000 weight for every XCM instruction
    // We are executing 4 instructions
    // 100_000_000 * 4 * 50000 = 20000000000000
    // We are charging 20 micro DEV for this operation
    // The rest should be going to the deposit account
    let xcmMessage = {
      V2: [
        {
          WithdrawAsset: [
            {
              // This is the new reanchored logic
              id: {
                Concrete: {
                  parents: 1,
                  interior: {
                    X2: [{ Parachain: ownParaId }, { PalletInstance: balancesPalletIndex }],
                  },
                },
              },
              fun: { Fungible: transferredBalance },
            },
            {
              // This is the new reanchored logic
              id: {
                Concrete: {
                  parents: 1,
                  interior: {
                    X3: [
                      { Parachain: ownParaId },
                      { PalletInstance: localAssetsPalletIndex },
                      { GeneralIndex: assetId },
                    ],
                  },
                },
              },
              fun: { Fungible: transferredBalance },
            },
          ],
        },
        { ClearOrigin: null },
        {
          BuyExecution: {
            fees: {
              id: {
                // This is the new reanchored logic
                Concrete: {
                  parents: 1,
                  interior: {
                    X2: [{ Parachain: ownParaId }, { PalletInstance: balancesPalletIndex }],
                  },
                },
              },
              fun: { Fungible: transferredBalance },
            },
            weightLimit: { Limited: new BN(4000000000) },
          },
        },
        {
          DepositAsset: {
            assets: { Wild: "All" },
            maxAssets: new BN(2),
            beneficiary: {
              parents: 0,
              interior: { X1: { AccountKey20: { network: "Any", key: baltathar.address } } },
            },
          },
        },
      ],
    };

    const xcmpFormat: XcmpMessageFormat = context.polkadotApi.createType(
      "XcmpMessageFormat",
      "ConcatenatedVersionedXcm"
    ) as any;
    const receivedMessage: XcmVersionedXcm = context.polkadotApi.createType(
      "XcmVersionedXcm",
      xcmMessage
    ) as any;

    const totalMessage = [...xcmpFormat.toU8a(), ...receivedMessage.toU8a()];
    // Send RPC call to inject XCM message
    // We will set a specific message knowing that it should mint the statemint asset
    await customWeb3Request(context.web3, "xcm_injectHrmpMessage", [foreign_para_id, totalMessage]);

    // Create a block in which the XCM will be executed
    await context.createBlock();

    // Old reanchor does not work anymore so no reception of tokens
    let baltatharLocalTokBalance = (await context.polkadotApi.query.localAssets.account(
      assetId,
      baltathar.address
    )) as any;

    expect(baltatharLocalTokBalance.isNone).to.eq(true);
  });
});