@polkadot/util#BN TypeScript Examples

The following examples show how to use @polkadot/util#BN. 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: Balance.ts    From gear-js with GNU General Public License v3.0 6 votes vote down vote up
transferFromAlice(to: string, value: number | BN, eventsCallback?: (event: any, data: any) => void): Promise<any> {
    return new Promise(async (resolve, reject) => {
      try {
        const unsub = await this.api.tx.balances
          .transfer(to, value)
          .signAndSend(await GearKeyring.fromSuri('//Alice', 'Alice default'), ({ events }) => {
            events.forEach(({ event: { data, method } }) => {
              if (eventsCallback) {
                eventsCallback(method, data);
              }
              if (method === 'Transfer') {
                unsub();
                resolve(0);
              }
            });
          });
      } catch (error) {
        reject(new TransactionError(error.message));
      }
    });
  }
Example #2
Source File: test-assets-pallet.ts    From moonbeam with GNU General Public License v3.0 6 votes vote down vote up
describeDevMoonbeam("Pallet Assets Pallet - assets transfer", (context) => {
  let sudoAccount, assetId;
  before("Test querying asset", async () => {
    const keyring = new Keyring({ type: "ethereum" });
    sudoAccount = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");

    // We need to mint units with sudo.setStorage, as we dont have xcm mocker yet
    // And we need relay tokens for issuing a transaction to be executed in the relay
    const balance = context.polkadotApi.createType("Balance", 100000000000000);
    const assetBalance = context.polkadotApi.createType("PalletAssetsAssetAccount", {
      balance: balance,
    });

    assetId = context.polkadotApi.createType(
      "u128",
      new BN("42259045809535163221576417993425387648")
    );
    const assetDetails = context.polkadotApi.createType("PalletAssetsAssetDetails", {
      supply: balance,
    });

    await mockAssetBalance(context, assetBalance, assetDetails, sudoAccount, assetId, ALITH);

    await createBlockWithExtrinsic(
      context,
      sudoAccount,
      context.polkadotApi.tx.assets.transfer(assetId, BALTATHAR, 1000)
    );
  });

  it("should query asset balance", async function () {
    // Baltathar balance is 1000
    let baltatharBalance = (await context.polkadotApi.query.assets.account(
      assetId,
      BALTATHAR
    )) as any;
    expect(baltatharBalance.unwrap()["balance"].eq(new BN(1000))).to.equal(true);
  });
});
Example #3
Source File: Balance.ts    From gear-js with GNU General Public License v3.0 6 votes vote down vote up
transferBalance(
    keyring: KeyringPair,
    to: string,
    value: number | BN,
    eventsCallback?: (event: any, data: any) => void,
  ): Promise<any> {
    return new Promise(async (resolve, reject) => {
      try {
        const unsub = await this.api.tx.balances.transfer(to, value).signAndSend(keyring, ({ events, status }) => {
          events.forEach(({ event: { data, method } }) => {
            if (eventsCallback) {
              eventsCallback(method, data);
            }
            if (method === 'Transfer') {
              unsub();
              resolve(0);
            }
          });
        });
      } catch (error) {
        reject(new TransactionError(error.message));
      }
    });
  }
Example #4
Source File: blockTime.ts    From contracts-ui with GNU General Public License v3.0 6 votes vote down vote up
export function blockTimeMs(a: OrFalsy<ApiPromise>): BN {
  return (a?.consts.babe?.expectedBlockTime || // Babe
    // POW, eg. Kulupu
    a?.consts.difficulty?.targetBlockTime ||
    // Check against threshold to determine value validity
    (a?.consts.timestamp?.minimumPeriod.gte(THRESHOLD)
      ? // Default minimum period config
        a.consts.timestamp.minimumPeriod.mul(BN_TWO)
      : a?.query.parachainSystem
      ? // default guess for a parachain
        DEFAULT_TIME.mul(BN_TWO)
      : // default guess for others
        DEFAULT_TIME)) as BN;
}
Example #5
Source File: test-xcm-para.ts    From moonbeam with GNU General Public License v3.0 6 votes vote down vote up
async function registerAssetToParachain(
  parachainApi: ApiPromise,
  sudoKeyring: KeyringPair,
  assetLocation: SourceLocation = sourceLocationRelay,
  assetMetadata: AssetMetadata = relayAssetMetadata
) {
  const { events: eventsRegister } = await createBlockWithExtrinsicParachain(
    parachainApi,
    sudoKeyring,
    parachainApi.tx.sudo.sudo(
      parachainApi.tx.assetManager.registerAsset(assetLocation, assetMetadata, new BN(1), true)
    )
  );
  let assetId: string;
  // Look for assetId in events
  eventsRegister.forEach((e) => {
    let ev = e.toHuman();
    if (ev.section === "assetManager") {
      assetId = ev.data[0];
    }
  });
  if (!assetId) {
    await new Promise((res) => setTimeout(res, 20000));
  }
  assetId = assetId.replace(/,/g, "");

  // setAssetUnitsPerSecond
  const { events } = await createBlockWithExtrinsicParachain(
    parachainApi,
    sudoKeyring,
    parachainApi.tx.sudo.sudo(parachainApi.tx.assetManager.setAssetUnitsPerSecond(assetLocation, 0))
  );
  return { events, assetId };
}
Example #6
Source File: gear.ts    From gear-js with GNU General Public License v3.0 5 votes vote down vote up
accountBalance: BN;
Example #7
Source File: blockTime.ts    From contracts-ui with GNU General Public License v3.0 5 votes vote down vote up
DEFAULT_TIME = new BN(6_000)
Example #8
Source File: test-assets-sufficients.ts    From moonbeam with GNU General Public License v3.0 5 votes vote down vote up
relayAssetMetadata: AssetMetadata = {
  name: "DOT",
  symbol: "DOT",
  decimals: new BN(12),
  isFrozen: false,
}
Example #9
Source File: useEstimatedFeePayload.ts    From parity-bridges-ui with GNU General Public License v3.0 4 votes vote down vote up
useEstimatedFeePayload = (
  transactionState: TransactionState,
  dispatchTransaction: Dispatch<TransactionsActionType>
) => {
  const { createType, stateCall } = useApiCallsContext();

  const laneId = useLaneId();
  const sourceTargetDetails = useSourceTarget();
  const {
    sourceChainDetails: {
      chain: sourceChain,
      apiConnection: { api: sourceApi }
    },
    targetChainDetails: {
      apiConnection: { api: targetApi },
      chain: targetChain
    }
  } = sourceTargetDetails;
  const { account, senderAccountBalance, senderCompanionAccountBalance } = useAccountContext();
  const { action, isBridged } = useGUIContext();
  const { estimatedFeeMethodName } = getSubstrateDynamicNames(targetChain);
  const previousPayloadEstimatedFeeLoading = usePrevious(transactionState.payloadEstimatedFeeLoading);
  const { bridgedMessages } = getSubstrateDynamicNames(targetChain);

  const dispatch = useCallback(
    (error: string | null, data: PayloadEstimatedFee | null, loading: boolean) =>
      dispatchTransaction(
        TransactionActionCreators.setPayloadEstimatedFee({
          payloadEstimatedFeeError: error,
          payloadEstimatedFee: data,
          payloadEstimatedFeeLoading: loading,
          sourceTargetDetails,
          createType,
          isBridged,
          senderAccountBalance,
          senderCompanionAccountBalance,
          chainDecimals: targetApi.registry.chainDecimals[0]
        })
      ),
    [
      createType,
      dispatchTransaction,
      isBridged,
      senderAccountBalance,
      senderCompanionAccountBalance,
      sourceTargetDetails,
      targetApi.registry.chainDecimals
    ]
  );

  const calculateFeeAndPayload = useCallback(
    async (currentTransactionState: TransactionState) => {
      if (currentTransactionState.action === TransactionTypes.INTERNAL_TRANSFER) {
        const { estimatedFee, weight } = await getFeeAndWeightForInternals({
          api: sourceApi,
          transactionState: currentTransactionState
        });
        const payload = {
          sourceAccount: currentTransactionState.senderAccount,
          transferAmount: currentTransactionState.transferAmount!.toNumber(),
          receiverAddress: currentTransactionState.receiverAddress,
          weight
        };
        return { estimatedSourceFee: estimatedFee, payload };
      }
      const { call, weight } = await getTransactionCallWeight({
        action,
        account,
        targetApi,
        transactionState: currentTransactionState
      });

      if (!call || !weight) {
        return emptyData;
      }

      const callToCompact = currentTransactionState.action === TransactionTypes.CUSTOM ? call : call.slice(2);
      const payload = {
        call: compactAddLength(callToCompact),
        origin: {
          SourceAccount: account!.addressRaw
        },
        dispatch_fee_payment: currentTransactionState.payFee,
        spec_version: targetApi.consts.system.version.specVersion.toNumber(),
        weight
      };

      const payloadType = createType(sourceChain as keyof InterfaceTypes, 'OutboundPayload', payload);
      logger.info(`OutboundPayload: ${JSON.stringify(payload)}`);
      logger.info(`OutboundPayload.toHex(): ${payloadType.toHex()}`);
      const messageFeeType = createType(sourceChain as keyof InterfaceTypes, 'MessageFeeData', {
        lane_id: laneId,
        payload: payloadType.toHex()
      });

      // estimatedFeeMessageDelivery
      const estimatedFeeCall = await stateCall(sourceChain, estimatedFeeMethodName, messageFeeType.toHex());
      const estimatedFeeType = createType(sourceChain as keyof InterfaceTypes, 'Option<Balance>', estimatedFeeCall);
      const estimatedFeeMessageDelivery = estimatedFeeType.toString();

      // estimatedFeeBridgeCall
      const bridgeMessage = sourceApi.tx[bridgedMessages].sendMessage(laneId, payload, estimatedFeeCall);
      const submitMessageTransactionFee = await sourceApi.rpc.payment.queryFeeDetails(bridgeMessage.toHex());
      const estimatedFeeBridgeCallBalance = (submitMessageTransactionFee as FeeDetails).inclusionFee.unwrap()
        .adjustedWeightFee;
      const estimatedFeeBridgeCall = estimatedFeeBridgeCallBalance.toString();

      // estimatedSourceFee calculation based on the sum of estimatedFeeMessageDelivery + estimatedFeeBridgeCallBalance
      const estimatedSourceFeeBN = new BN(estimatedFeeMessageDelivery).add(estimatedFeeBridgeCallBalance.toBn());
      const estimatedSourceFee = estimatedSourceFeeBN.toString();

      // estimatedTargetFee
      const targetFeeDetails = await targetApi.rpc.payment.queryFeeDetails(u8aToHex(call));
      const estimatedTargetFee = (targetFeeDetails as FeeDetails).inclusionFee.unwrap().adjustedWeightFee.toString();

      return {
        estimatedSourceFee,
        estimatedFeeMessageDelivery,
        estimatedFeeBridgeCall,
        estimatedTargetFee,
        payload
      };
    },
    [
      account,
      action,
      bridgedMessages,
      createType,
      estimatedFeeMethodName,
      laneId,
      sourceApi,
      sourceChain,
      stateCall,
      targetApi
    ]
  );

  useEffect(() => {
    const { shouldEvaluatePayloadEstimatedFee, payloadEstimatedFeeLoading } = transactionState;

    if (shouldEvaluatePayloadEstimatedFee && payloadEstimatedFeeLoading) {
      logger.info(
        'Transaction information changed while estimated fee is being calculating. Batching the new calculation.'
      );
      dispatchTransaction(TransactionActionCreators.setBatchedEvaluationPayloadEstimatedFee(transactionState));
    }
    if (shouldEvaluatePayloadEstimatedFee && !payloadEstimatedFeeLoading) {
      genericCall({
        //@ts-ignore
        call: () => calculateFeeAndPayload(transactionState),
        dispatch,
        emptyData
      });
    }
  }, [calculateFeeAndPayload, dispatch, dispatchTransaction, transactionState]);

  useEffect(() => {
    const { batchedTransactionState, payloadEstimatedFeeLoading } = transactionState;

    if (
      previousPayloadEstimatedFeeLoading &&
      !payloadEstimatedFeeLoading &&
      batchedTransactionState &&
      senderAccountBalance &&
      senderCompanionAccountBalance
    ) {
      genericCall({
        //@ts-ignore
        call: () => calculateFeeAndPayload(batchedTransactionState),
        dispatch,
        emptyData
      });
      dispatchTransaction(TransactionActionCreators.setBatchedEvaluationPayloadEstimatedFee(null));
    }
  }, [
    account,
    calculateFeeAndPayload,
    dispatch,
    dispatchTransaction,
    previousPayloadEstimatedFeeLoading,
    senderAccountBalance,
    senderCompanionAccountBalance,
    transactionState
  ]);
}
Example #10
Source File: Transfer.tsx    From subscan-multisig-react with Apache License 2.0 4 votes vote down vote up
// eslint-disable-next-line complexity
function Transfer({
  className = '',
  onClose,
  onTxSuccess,
  recipientId: propRecipientId,
  senderId: propSenderId,
}: Props): React.ReactElement<Props> {
  const { t } = useTranslation();
  const { api } = useApi();
  const { multisigAccount } = useMultisig();
  const [amount, setAmount] = useState<BN | undefined>(BN_ZERO);
  const [hasAvailable] = useState(true);
  const [isProtected, setIsProtected] = useState(true);
  const [isAll, setIsAll] = useState(false);
  const [[maxTransfer, noFees], setMaxTransfer] = useState<[BN | null, boolean]>([null, false]);
  const [recipientId, setRecipientId] = useState<string | null>(null);
  const [senderId, setSenderId] = useState<string | null>(null);
  const [[, recipientPhish], setPhishing] = useState<[string | null, string | null]>([null, null]);
  const balances = useCall<DeriveBalancesAll>(api.derive.balances?.all, [propSenderId || senderId]);
  const accountInfo = useCall<AccountInfoWithProviders | AccountInfoWithRefCount>(api.query.system.account, [
    propSenderId || senderId,
  ]);
  const [multisigExtrinsic, setMultisigExtrinsic] = useState<SubmittableExtrinsic<'promise'> | null>(null);
  const [accountId, setAccountId] = useState<string | null>(null);
  const isExtensionAccount = useIsInjected();
  const [reserveAmount, setReserveAmount] = useState(0);

  const options = useMemo<KeyringSectionOption[]>(
    () =>
      ((multisigAccount?.meta?.addressPair as AddressPair[]) ?? []).map(({ address, ...others }) => ({
        ...others,
        value: address,
        key: address,
      })),
    [multisigAccount?.meta]
  );
  const [optionsAll, setOptionsAll] = useState<Record<string, Option[]>>({
    account: [],
    all: [],
  });

  const [depositBase, depositFactor] = useMemo(() => {
    return [Number(api?.consts.multisig.depositBase.toJSON()), Number(api?.consts.multisig.depositFactor.toJSON())];
  }, [api]);

  const [chainDecimal, chainToken] = useMemo(() => {
    return [api?.registry.chainDecimals[0], api?.registry.chainTokens[0]];
  }, [api]);

  const createMultiItem = useCallback(
    (option: Option): Option[] => {
      if (option.value === multisigAccount?.address) {
        return options.map((opt) => createItem(opt));
      }

      return [];
    },
    [multisigAccount?.address, options]
  );

  useEffect(() => {
    const subscription = keyring.keyringOption.optionsSubject.subscribe((all) => {
      const optAll = Object.entries(all).reduce(
        (
          result: Record<string, (Option | React.ReactNode)[]>,
          [type, value]
        ): Record<string, (Option | React.ReactNode)[]> => {
          result[type] = flatten(
            value.map((option): Option | React.ReactNode =>
              option.value === null
                ? createHeader(option)
                : createMultiItem(option as Option).filter((item) => isExtensionAccount(item.value))
            )
          );

          return result;
        },
        {}
      );

      setOptionsAll(optAll as Record<string, Option[]>);
    });

    return () => subscription.unsubscribe();
  }, [createMultiItem, isExtensionAccount]);

  // eslint-disable-next-line complexity
  useEffect((): void => {
    const fromId = propSenderId || (senderId as string);
    const toId = propRecipientId || (recipientId as string);

    if (balances && balances.accountId?.eq(fromId) && fromId && toId && isFunction(api.rpc.payment?.queryInfo)) {
      setTimeout((): void => {
        try {
          api.tx.balances
            ?.transfer(toId, balances.availableBalance)
            .paymentInfo(fromId)
            .then(({ partialFee }): void => {
              // eslint-disable-next-line no-magic-numbers
              const adjFee = partialFee.muln(110).div(BN_HUNDRED);
              const tempMaxTransfer = balances.availableBalance.sub(adjFee);

              setMaxTransfer(
                tempMaxTransfer.gt(api.consts.balances?.existentialDeposit as unknown as BN)
                  ? [tempMaxTransfer, false]
                  : [null, true]
              );
            })
            .catch(console.error);
        } catch (error) {
          console.error((error as Error).message);
        }
      }, 0);
    } else {
      setMaxTransfer([null, false]);
    }
  }, [api, balances, propRecipientId, propSenderId, recipientId, senderId]);

  useEffect((): void => {
    checkPhishing(propSenderId || senderId, propRecipientId || recipientId)
      .then(setPhishing)
      .catch(console.error);
  }, [propRecipientId, propSenderId, recipientId, senderId]);

  const noReference = accountInfo
    ? isRefcount(accountInfo)
      ? accountInfo.refcount.isZero()
      : accountInfo.consumers.isZero()
    : true;
  const canToggleAll =
    !isProtected && balances && balances.accountId?.eq(propSenderId || senderId) && maxTransfer && noReference;

  useEffect(() => {
    // eslint-disable-next-line complexity
    (async () => {
      const fn =
        canToggleAll && isAll && isFunction(api.tx.balances?.transferAll)
          ? api.tx.balances?.transferAll
          : isProtected
          ? api.tx.balances?.transferKeepAlive
          : api.tx.balances?.transfer;

      if (!fn || !propSenderId) {
        setMultisigExtrinsic(null);
        return;
      }

      const params =
        canToggleAll && isAll && isFunction(api.tx.balances?.transferAll)
          ? [{ Id: recipientId }, amount]
          : isProtected
          ? [{ Id: recipientId }, amount]
          : [{ Id: recipientId }, amount];

      const ext = fn(...params);

      // eslint-disable-next-line no-console
      // console.log('amount', amount?.toString());

      const ARG_LENGTH = 6;
      const info = await api?.query.multisig.multisigs(propSenderId, ext?.method.hash);
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const timepoint = (info as any).isSome ? (info as any)?.unwrap().when : null;
      const { threshold, who } = extractExternal(propSenderId);
      const others: string[] = who.filter((item) => item !== accountId);
      const { weight } = (await ext?.paymentInfo(propSenderId)) || { weight: 0 };
      const module = api?.tx.multisig;
      const argsLength = module?.asMulti.meta.args.length || 0;
      const generalParams = [threshold, others, timepoint];
      const args =
        argsLength === ARG_LENGTH ? [...generalParams, ext.method.toHex(), true, weight] : [...generalParams, ext];
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const multiTx = module?.asMulti(...args);

      // eslint-disable-next-line no-console
      // console.log('hexCallData', ext.method.toHex());

      setMultisigExtrinsic(multiTx);

      // Estimate reserve amount
      try {
        if (chainDecimal) {
          setReserveAmount(
            // eslint-disable-next-line no-magic-numbers
            (depositBase * 2 + depositFactor * threshold + (depositFactor * (ext.method.toHex().length + 31)) / 32) /
              Math.pow(10, chainDecimal)
          );
        }
      } catch (err) {
        setReserveAmount(0);
      }
    })();
  }, [
    canToggleAll,
    isAll,
    api,
    isProtected,
    amount,
    recipientId,
    propSenderId,
    accountId,
    chainDecimal,
    depositBase,
    depositFactor,
  ]);

  return (
    <Modal className="app--accounts-Modal" header={t<string>('Send funds')} onClose={onClose} size="large">
      <Modal.Content>
        <div className={className}>
          <Modal.Columns
            hint={t<string>('The transferred balance will be subtracted (along with fees) from the sender account.')}
          >
            <PureInputAddress
              label={t<string>('using the selected account')}
              labelExtra={<BalanceFree label={<label>{t<string>('free balance')}</label>} params={accountId} />}
              onChange={setAccountId}
              optionsAll={optionsAll}
              type="account"
            />
          </Modal.Columns>
          <Modal.Columns
            hint={t<string>('The transferred balance will be subtracted (along with fees) from the sender account.')}
          >
            <InputAddress
              defaultValue={propSenderId}
              help={t<string>('The account you will send funds from.')}
              isDisabled={!!propSenderId}
              label={t<string>('send from account')}
              labelExtra={<Available label={t<string>('transferrable')} params={propSenderId || senderId} />}
              onChange={setSenderId}
              type="account"
            />
          </Modal.Columns>
          <Modal.Columns
            hint={t<string>(
              'The beneficiary will have access to the transferred fees when the transaction is included in a block.'
            )}
          >
            <InputAddress
              defaultValue={propRecipientId}
              help={t<string>('Select a contact or paste the address you want to send funds to.')}
              isDisabled={!!propRecipientId}
              label={t<string>('send to address')}
              labelExtra={<Available label={t<string>('transferrable')} params={propRecipientId || recipientId} />}
              onChange={setRecipientId}
              type="allPlus"
            />
            {recipientPhish && (
              <MarkError
                content={t<string>('The recipient is associated with a known phishing site on {{url}}', {
                  replace: { url: recipientPhish },
                })}
              />
            )}
          </Modal.Columns>
          <Modal.Columns
            hint={t<string>(
              'If the recipient account is new, the balance needs to be more than the existential deposit. Likewise if the sending account balance drops below the same value, the account will be removed from the state.'
            )}
          >
            {canToggleAll && isAll ? (
              <InputBalance
                autoFocus
                defaultValue={maxTransfer}
                help={t<string>('The full account balance to be transferred, minus the transaction fees')}
                isDisabled
                key={maxTransfer?.toString()}
                label={t<string>('transferrable minus fees')}
              />
            ) : (
              <>
                <InputBalance
                  autoFocus
                  help={t<string>(
                    'Type the amount you want to transfer. Note that you can select the unit on the right e.g sending 1 milli is equivalent to sending 0.001.'
                  )}
                  isError={!hasAvailable}
                  isZeroable
                  label={t<string>('amount')}
                  maxValue={maxTransfer}
                  onChange={setAmount}
                />
                <InputBalance
                  defaultValue={api.consts.balances?.existentialDeposit}
                  help={t<string>('The minimum amount that an account should have to be deemed active')}
                  isDisabled
                  label={t<string>('existential deposit')}
                />
              </>
            )}
          </Modal.Columns>
          <Modal.Columns
            hint={t('With the keep-alive option set, the account is protected against removal due to low balances.')}
          >
            {isFunction(api.tx.balances?.transferKeepAlive) && (
              <Toggle
                className="typeToggle"
                label={
                  isProtected
                    ? t<string>('Transfer with account keep-alive checks')
                    : t<string>('Normal transfer without keep-alive checks')
                }
                onChange={setIsProtected}
                value={isProtected}
              />
            )}
            {canToggleAll && (
              <Toggle
                className="typeToggle"
                label={t<string>('Transfer the full account balance, reap the sender')}
                onChange={setIsAll}
                value={isAll}
              />
            )}
            {!isProtected && !noReference && (
              <MarkWarning
                content={t<string>(
                  'There is an existing reference count on the sender account. As such the account cannot be reaped from the state.'
                )}
              />
            )}
            {noFees && (
              <MarkWarning
                content={t<string>(
                  'The transaction, after application of the transfer fees, will drop the available balance below the existential deposit. As such the transfer will fail. The account needs more free funds to cover the transaction fees.'
                )}
              />
            )}
          </Modal.Columns>
        </div>
      </Modal.Content>

      <div className="flex items-center justify-between px-5">
        <Text style={{ color: 'rgba(78,78,78,0.6)', marginLeft: '20px' }}>
          {t('multisig.estimate_reserve')} {reserveAmount} {chainToken}
        </Text>

        <Modal.Actions onCancel={onClose}>
          <TxButton
            // accountId={propSenderId || senderId}
            accountId={accountId}
            icon="paper-plane"
            isDisabled={!hasAvailable || !(propRecipientId || recipientId) || !amount || !!recipientPhish}
            label={t<string>('Make Transfer')}
            onStart={onClose}
            extrinsic={multisigExtrinsic}
            onSuccess={onTxSuccess}
            // params={
            //   canToggleAll && isAll
            //     ? isFunction(api.tx.balances?.transferAll)
            //       ? [propRecipientId || recipientId, false]
            //       : [propRecipientId || recipientId, maxTransfer]
            //     : [propRecipientId || recipientId, amount]
            // }
            // tx={
            //   canToggleAll && isAll && isFunction(api.tx.balances?.transferAll)
            //     ? api.tx.balances?.transferAll
            //     : isProtected
            //     ? api.tx.balances?.transferKeepAlive
            //     : api.tx.balances?.transfer
            // }
          />
        </Modal.Actions>
      </div>
    </Modal>
  );
}
Example #11
Source File: test-assets-sufficients.ts    From moonbeam with GNU General Public License v3.0 4 votes vote down vote up
describeDevMoonbeam(
  "Pallet Assets - Sufficient tests: is_sufficient to true",
  (context) => {
    let sudoAccount, assetId;
    before("Setup contract and mock balance", async () => {
      const keyring = new Keyring({ type: "ethereum" });
      sudoAccount = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
      // We need to mint units with sudo.setStorage, as we dont have xcm mocker yet
      // And we need relay tokens for issuing a transaction to be executed in the relay
      const balance = new BN("100000000000000");
      const assetBalance = context.polkadotApi.createType("PalletAssetsAssetAccount", {
        balance: balance,
      });
      assetId = context.polkadotApi.createType(
        "u128",
        new BN("42259045809535163221576417993425387648")
      );

      const assetDetails = context.polkadotApi.createType("PalletAssetsAssetDetails", {
        supply: balance,
        isSufficient: true,
        minBalance: 1,
      });

      await mockAssetBalance(
        context,
        assetBalance,
        assetDetails,
        sudoAccount,
        assetId,
        ALITH,
        true
      );

      await context.createBlock();
      let alithBalance = (await context.polkadotApi.query.assets.account(assetId, ALITH)) as any;
      expect(alithBalance.unwrap()["balance"].eq(new BN(100000000000000))).to.equal(true);
    });

    it("Send MOVR and assets to an account, then drain assets, then MOVR", async function () {
      // We are going to use a fresh account here, since we mocked the asset balance
      const keyring = new Keyring({ type: "ethereum" });
      const alith = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
      const seed = randomAsHex(32);
      const transferAmount = new BN("10000000000000");

      let freshAccount = await keyring.addFromUri(seed, null, "ethereum");

      // We transfer Assets to freshAccount, which should increase sufficients
      await context.polkadotApi.tx.assets
        .transfer(assetId, freshAccount.address, transferAmount)
        .signAndSend(alith);

      await context.createBlock();

      let freshAccountBalance = (await context.polkadotApi.query.assets.account(
        assetId,
        freshAccount.address
      )) as any;

      expect(freshAccountBalance.unwrap()["balance"].eq(new BN(10000000000000))).to.equal(true);

      expect(
        (
          (await context.polkadotApi.query.system.account(freshAccount.address)) as any
        ).sufficients.toBigInt()
      ).to.eq(1n);
      // Providers should still be 0
      expect(
        (
          (await context.polkadotApi.query.system.account(freshAccount.address)) as any
        ).providers.toBigInt()
      ).to.eq(0n);

      // We transfer a good amount to be able to pay for fees
      await context.polkadotApi.tx.balances
        .transfer(freshAccount.address, 1n * GLMR)
        .signAndSend(alith);
      await context.createBlock();

      expect(
        (
          (await context.polkadotApi.query.system.account(freshAccount.address)) as any
        ).sufficients.toBigInt()
      ).to.eq(1n);

      // Providers should now be 1
      expect(
        (
          (await context.polkadotApi.query.system.account(freshAccount.address)) as any
        ).providers.toBigInt()
      ).to.eq(1n);

      // Let's drain assets
      await context.polkadotApi.tx.assets
        .transfer(assetId, BALTATHAR, transferAmount)
        .signAndSend(freshAccount);

      await context.createBlock();

      // Lets drain native token
      // First calculate fee
      // Then grab balance of freshAccount
      // Then we just transfer out balance of freshAccount - fee
      const fee = (
        await context.polkadotApi.tx.balances.transfer(ALITH, 1n * GLMR).paymentInfo(freshAccount)
      ).partialFee as any;

      let freshAccountBalanceNativeToken = (
        (await context.polkadotApi.query.system.account(freshAccount.address)) as any
      ).data.free.toBigInt();

      await context.polkadotApi.tx.balances
        .transfer(BALTATHAR, freshAccountBalanceNativeToken - BigInt(fee))
        .signAndSend(freshAccount);

      await context.createBlock();

      freshAccountBalance = (await context.polkadotApi.query.assets.account(
        assetId,
        freshAccount.address
      )) as any;
      expect(freshAccountBalance.isNone).to.equal(true);

      // Sufficients should go to 0
      expect(
        (
          (await context.polkadotApi.query.system.account(freshAccount.address)) as any
        ).sufficients.toBigInt()
      ).to.eq(0n);
      // Providers should be 1
      expect(
        (
          (await context.polkadotApi.query.system.account(freshAccount.address)) as any
        ).providers.toBigInt()
      ).to.eq(1n);

      // Nonce should be 1
      expect(
        (
          (await context.polkadotApi.query.system.account(freshAccount.address)) as any
        ).providers.toBigInt()
      ).to.eq(1n);

      // But balance of MOVR should be 0
      expect(
        (
          (await context.polkadotApi.query.system.account(freshAccount.address)) as any
        ).data.free.toBigInt()
      ).to.eq(0n);
    });
  },
  "Legacy",
  true
);