@polkadot/types/interfaces#H256 TypeScript Examples

The following examples show how to use @polkadot/types/interfaces#H256. 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: replace.ts    From interbtc-api with Apache License 2.0 6 votes vote down vote up
async getRequestById(replaceId: H256 | string): Promise<ReplaceRequestExt> {
        const head = await this.api.rpc.chain.getFinalizedHead();
        return parseReplaceRequest(
            this.vaultsAPI,
            await this.api.query.replace.replaceRequests.at(head, ensureHashEncoded(this.api, replaceId)),
            this.btcNetwork,
            this.wrappedCurrency,
            replaceId
        );
    }
Example #2
Source File: requests.ts    From polkabtc-ui with Apache License 2.0 6 votes vote down vote up
parachainToUIReplaceRequests = (requests: Map<H256, ParachainReplaceRequest>): VaultReplaceRequest[] => {
  const replaceRequests: VaultReplaceRequest[] = [];
  requests.forEach((request, requestId) => {
    const [btcAddress, polkaBTC, lockedDOT] = convertParachainTypes(request);
    replaceRequests.push({
      id: stripHexPrefix(requestId.toString()),
      timestamp: request.btc_height.toString(),
      newVault: request.new_vault.toString(),
      oldVault: request.old_vault.toString(),
      btcAddress: btcAddress,
      polkaBTC: polkaBTC,
      lockedDOT: lockedDOT,
      status: parseReplaceRequestStatus(request.status)
    });
  });
  return replaceRequests;
}
Example #3
Source File: encoding.ts    From interbtc-api with Apache License 2.0 6 votes vote down vote up
export async function parseRedeemRequest(
    vaultsAPI: VaultsAPI,
    req: InterbtcPrimitivesRedeemRedeemRequest,
    network: Network,
    id: H256 | string
): Promise<Redeem> {
    const status = req.status.isCompleted
        ? RedeemStatus.Completed
        : req.status.isRetried
            ? RedeemStatus.Retried
            : req.status.isReimbursed
                ? RedeemStatus.Reimbursed
                : RedeemStatus.PendingWithBtcTxNotFound;

    const currencyIdLiteral = currencyIdToLiteral(req.vault.currencies.collateral);
    const vault = await vaultsAPI.get(req.vault.accountId, currencyIdLiteral);
    const collateralCurrency = currencyIdToMonetaryCurrency(vault.id.currencies.collateral) as Currency<CollateralUnit>;
    return {
        id: stripHexPrefix(id.toString()),
        userParachainAddress: req.redeemer.toString(),
        amountBTC: newMonetaryAmount(req.amountBtc.toString(), vaultsAPI.getWrappedCurrency()),
        collateralPremium: newMonetaryAmount(req.premium.toString(), collateralCurrency),
        bridgeFee: newMonetaryAmount(req.fee.toString(), vaultsAPI.getWrappedCurrency()),
        btcTransferFee: newMonetaryAmount(req.transferFeeBtc.toString(), vaultsAPI.getWrappedCurrency()),
        creationBlock: req.opentime.toNumber(),
        vaultId: req.vault,
        userBTCAddress: encodeBtcAddress(req.btcAddress, network),
        status,
    };
}
Example #4
Source File: encoding.ts    From interbtc-api with Apache License 2.0 6 votes vote down vote up
export async function parseIssueRequest(
    vaultsAPI: VaultsAPI,
    req: InterbtcPrimitivesIssueIssueRequest,
    network: Network,
    id: H256 | string
): Promise<Issue> {
    const status = req.status.isCompleted
        ? IssueStatus.Completed
        : req.status.isCancelled
            ? IssueStatus.Cancelled
            : IssueStatus.PendingWithBtcTxNotFound;
    const collateralCurrency = currencyIdToMonetaryCurrency(
        req.vault.currencies.collateral
    ) as Currency<CollateralUnit>;
    return {
        id: stripHexPrefix(id.toString()),
        creationBlock: req.opentime.toNumber(),
        vaultWrappedAddress: encodeBtcAddress(req.btcAddress, network),
        vaultId: req.vault,
        userParachainAddress: req.requester.toString(),
        vaultWalletPubkey: req.btcPublicKey.toString(),
        bridgeFee: newMonetaryAmount(req.fee.toString(), vaultsAPI.getWrappedCurrency()),
        wrappedAmount: newMonetaryAmount(req.amount.toString(), vaultsAPI.getWrappedCurrency()),
        griefingCollateral: newMonetaryAmount(req.griefingCollateral.toString(), collateralCurrency),
        status,
    };
}
Example #5
Source File: encoding.ts    From interbtc-api with Apache License 2.0 6 votes vote down vote up
export async function parseReplaceRequest(
    vaultsAPI: VaultsAPI,
    req: InterbtcPrimitivesReplaceReplaceRequest,
    network: Network,
    wrappedCurrency: WrappedCurrency,
    id: H256 | string
): Promise<ReplaceRequestExt> {
    const currencyIdLiteral = currencyIdToLiteral(req.oldVault.currencies.collateral);
    const oldVault = await vaultsAPI.get(req.oldVault.accountId, currencyIdLiteral);
    const collateralCurrency = currencyIdToMonetaryCurrency(
        oldVault.id.currencies.collateral
    ) as Currency<CollateralUnit>;
    return {
        id: stripHexPrefix(id.toString()),
        btcAddress: encodeBtcAddress(req.btcAddress, network),
        newVault: req.newVault,
        oldVault: req.oldVault,
        amount: newMonetaryAmount(req.amount.toString(), wrappedCurrency),
        griefingCollateral: newMonetaryAmount(req.griefingCollateral.toString(), collateralCurrency),
        collateral: newMonetaryAmount(req.collateral.toString(), collateralCurrency),
        acceptTime: req.acceptTime.toNumber(),
        period: req.period.toNumber(),
        btcHeight: req.btcHeight.toNumber(),
        status: req.status,
    };
}
Example #6
Source File: encoding.ts    From interbtc-api with Apache License 2.0 6 votes vote down vote up
/**
 * Ensure a hash value is an encoded H256
 * @param api The polkadot API promise used to encode if necessary
 * @param hash The either H256 or string encoded hash
 **/
export function ensureHashEncoded(api: ApiPromise, hash: H256 | string): H256 {
    if (typeof hash === "string") {
        return api.createType("H256", addHexPrefix(hash as string));
    } else {
        return hash as H256;
    }
}
Example #7
Source File: replace.ts    From interbtc-api with Apache License 2.0 6 votes vote down vote up
async parseRequestsAsync(
        requestPairs: [H256, InterbtcPrimitivesReplaceReplaceRequest][]
    ): Promise<[H256, ReplaceRequestExt][]> {
        return await Promise.all(
            requestPairs.map(
                ([id, req]) =>
                    new Promise<[H256, ReplaceRequestExt]>((resolve) => {
                        parseReplaceRequest(this.vaultsAPI, req, this.btcNetwork, this.wrappedCurrency, id).then(
                            (replaceRequest) => {
                                resolve([id, replaceRequest]);
                            }
                        );
                    })
            )
        );
    }
Example #8
Source File: replace.ts    From interbtc-api with Apache License 2.0 6 votes vote down vote up
async map(): Promise<Map<H256, ReplaceRequestExt>> {
        const head = await this.api.rpc.chain.getFinalizedHead();
        const replaceRequests = await this.api.query.replace.replaceRequests.entriesAt(head);
        const replaceRequestMap = new Map<H256, ReplaceRequestExt>();
        await Promise.all(
            replaceRequests
                .filter((v) => v[1].isSome.valueOf)
                // Can be unwrapped because the filter removes `None` values
                .map(
                    ([id, req]) =>
                        new Promise<void>((resolve) => {
                            parseReplaceRequest(
                                this.vaultsAPI,
                                req.unwrap(),
                                this.btcNetwork,
                                this.wrappedCurrency,
                                storageKeyToNthInner(id)
                            ).then((replaceRequest) => {
                                replaceRequestMap.set(storageKeyToNthInner(id), replaceRequest);
                                resolve();
                            });
                        })
                )
        );
        return replaceRequestMap;
    }
Example #9
Source File: refund.ts    From interbtc-api with Apache License 2.0 6 votes vote down vote up
async getRequestById(refundId: H256): Promise<RefundRequestExt> {
        const head = await this.api.rpc.chain.getFinalizedHead();
        try {
            return parseRefundRequest(
                (await this.api.query.refund.refundRequests.at(head, refundId)).unwrap(),
                this.btcNetwork,
                this.wrappedCurrency
            );
        } catch (error) {
            return Promise.reject(new Error(`Error fetching refund request by issue id: ${error}`));
        }
    }
Example #10
Source File: redeem.ts    From interbtc-api with Apache License 2.0 6 votes vote down vote up
async getRequestsByIds(redeemIds: (H256 | string)[]): Promise<Redeem[]> {
        const redeemRequestData = await Promise.all(
            redeemIds.map(
                async (redeemId): Promise<[Option<InterbtcPrimitivesRedeemRedeemRequest>, H256 | string]> =>
                    new Promise((resolve, reject) => {
                        this.api.query.redeem
                            .redeemRequests(ensureHashEncoded(this.api, redeemId))
                            .then((request) => resolve([request, redeemId]))
                            .catch(reject);
                    })
            )
        );
        return Promise.all(
            redeemRequestData
                .filter(([option, _]) => option.isSome)
                .map(([redeemRequest, redeemId]) =>
                    parseRedeemRequest(this.vaultsAPI, redeemRequest.unwrap(), this.btcNetwork, redeemId)
                )
        );
    }
Example #11
Source File: issue.ts    From interbtc-api with Apache License 2.0 6 votes vote down vote up
async getRequestsByIds(issueIds: (H256 | string)[]): Promise<Issue[]> {
        const head = await this.api.rpc.chain.getFinalizedHead();
        const issueRequestData = await Promise.all(
            issueIds.map(
                async (issueId): Promise<[Option<InterbtcPrimitivesIssueIssueRequest>, H256 | string]> =>
                    new Promise((resolve, reject) => {
                        this.api.query.issue.issueRequests
                            .at(head, ensureHashEncoded(this.api, issueId))
                            .then((request) => resolve([request, issueId]))
                            .catch(reject);
                    })
            )
        );
        return Promise.all(
            issueRequestData
                .filter(([option, _]) => option.isSome)
                .map(([issueRequest, issueId]) =>
                    parseIssueRequest(this.vaultsAPI, issueRequest.unwrap(), this.btcNetwork, issueId)
                )
        );
    }
Example #12
Source File: Message.ts    From gear-js with GNU General Public License v3.0 6 votes vote down vote up
/**
   * Send message
   * @param message Message parameters
   * @param meta Metadata
   * @param messageType MessageType
   * @returns Submitted result
   * ```javascript
   * const api = await GearApi.create()
   * const programId = '0xd7540ae9da85e33b47276e2cb4efc2f0b58fef1227834f21ddc8c7cb551cced6'
   * api.message.submit({
   *  destination: messageId,
   *  payload: 'Hello, World!',
   *  gasLimit: 20_000_000
   * }, undefiend, 'String')
   * api.message.signAndSend(account, (events) => {
   *  events.forEach(({event}) => console.log(event.toHuman()))
   * })
   * ```
   */
  submit(
    message: { destination: string | H256; payload: PayloadType; gasLimit: AnyNumber; value?: AnyNumber },
    meta?: Metadata,
    messageType?: string,
  ): SubmittableExtrinsic<'promise', ISubmittableResult> {
    let payload = createPayload(this.createType, messageType || meta?.handle_input, message.payload, meta);
    try {
      this.submitted = this.api.tx.gear.sendMessage(message.destination, payload, message.gasLimit, message.value || 0);
      return this.submitted;
    } catch (error) {
      throw new SendMessageError();
    }
  }
Example #13
Source File: Mailbox.ts    From gear-js with GNU General Public License v3.0 6 votes vote down vote up
/**
   * Read mailbox
   * @param accountId
   * @returns
   * @example
   * ```javascript
   * const api = await GearApi.create();
   * const mailbox = await api.mailbox.read('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY');
   * console.log(mailbox);
   * ```
   */
  async read(accountId: Hex | AccountId32 | string, messageId?: Hex | H256): Promise<MailboxType> {
    if (messageId) {
      const mailbox = await this.api.query.gearMessenger.mailbox(accountId, messageId);
      return mailbox.toHuman() as MailboxType;
    } else {
      const keys = await this.api.query.gearMessenger.mailbox.keys(accountId);
      if (keys.length === 0) {
        return [];
      }
      const keyPrefixes = this.api.query.gearMessenger.mailbox.keyPrefix(accountId);
      const keysPaged = await this.api.rpc.state.getKeysPaged(keyPrefixes, 1000, keyPrefixes);
      const mailbox = (await this.api.rpc.state.queryStorageAt(keysPaged)) as Option<StoredMessage>[];
      return mailbox.map((option, index) => {
        return [
          keys[index].toHuman() as [AccountId, MessageId],
          this.api.createType('GearCoreMessageStoredStoredMessage', option.unwrap()).toHuman() as unknown,
        ];
      }) as MailboxType;
    }
  }
Example #14
Source File: useMultisigApprovals.ts    From crust-apps with Apache License 2.0 5 votes vote down vote up
export default function useMultisigApprovals (address: string): [H256, Multisig][] {
  const events = useContext(EventsContext);
  const { api } = useApi();
  const [multiInfos, setMultiInfos] = useState<[H256, Multisig][]>([]);
  const [trigger, incTrigger] = useIncrement();
  const mountedRef = useIsMountedRef();

  // increment the trigger by looking at all events
  //   - filter the by multisig module (old utility is not supported)
  //   - find anything data item where the type is AccountId
  //   - increment the trigger when at least one matches our address
  useEffect((): void => {
    events
      .filter(({ record: { event: { section } } }) => section === 'multisig')
      .reduce((hasMultisig: boolean, { record: { event: { data } } }) =>
        data.reduce((hasMultisig: boolean, item) =>
          hasMultisig || (item.toRawType() === 'AccountId' && item.eq(address)),
        hasMultisig),
      false) && incTrigger();
  }, [address, events, incTrigger]);

  // query all the entries for the multisig, extracting approvals with their hash
  useEffect((): void => {
    const multiModule = api.query.multisig || api.query.utility;

    multiModule && multiModule.multisigs &&
      multiModule.multisigs
        .entries(address)
        .then((infos: [StorageKey, Option<Multisig>][]): void => {
          mountedRef.current && setMultiInfos(
            infos
              .filter(([, opt]) => opt.isSome)
              .map(([key, opt]) => [key.args[1] as H256, opt.unwrap()])
          );
        })
        .catch(console.error);
  }, [address, api, mountedRef, trigger]);

  return multiInfos;
}
Example #15
Source File: redeem.ts    From interbtc-api with Apache License 2.0 5 votes vote down vote up
async getRequestById(redeemId: H256 | string): Promise<Redeem> {
        const id = ensureHashEncoded(this.api, redeemId);
        return (await this.getRequestsByIds([id]))[0];
    }
Example #16
Source File: issue.ts    From interbtc-api with Apache License 2.0 5 votes vote down vote up
async getRequestById(issueId: H256 | string): Promise<Issue> {
        return (await this.getRequestsByIds([issueId]))[0];
    }
Example #17
Source File: MessageReply.ts    From gear-js with GNU General Public License v3.0 5 votes vote down vote up
/**
   * Sends reply message
   * @param message Message parameters
   * @param meta Metadata
   * @param messageType MessageType
   * @returns Submitted result
   * @example
   * ```javascript
   * const api = await GearApi.create()
   * const messageId = '0xd7540ae9da85e33b47276e2cb4efc2f0b58fef1227834f21ddc8c7cb551cced6'
   * api.reply.submit({
   *  replyToId: messageId,
   *  payload: 'Reply message',
   *  gasLimit: 20_000_000
   * }, undefiend, 'String')
   * api.reply.signAndSend(account, (events) => {
   *  events.forEach(({event}) => console.log(event.toHuman()))
   * })
   * ```
   */
  submit(
    message: {
      replyToId: H256 | string;
      payload: string | any;
      gasLimit: u64 | AnyNumber;
      value?: BalanceOf | AnyNumber;
    },
    meta?: Metadata,
    messageType?: string,
  ): SubmittableExtrinsic<'promise', ISubmittableResult> {
    let payload = createPayload(
      this.createType,
      messageType || meta?.async_handle_input || meta?.async_init_input,
      message.payload,
      meta,
    );

    try {
      this.submitted = this.api.tx.gear.sendReply(message.replyToId, payload, message.gasLimit, message.value);
      return this.submitted;
    } catch (error) {
      throw new SendReplyError();
    }
  }
Example #18
Source File: vault.reducer.ts    From interbtc-ui with Apache License 2.0 5 votes vote down vote up
initialState = {
  requests: new Map<H256, ReplaceRequestExt>(),
  collateralization: '0',
  collateral: newMonetaryAmount(0, COLLATERAL_TOKEN),
  lockedBTC: BitcoinAmount.zero,
  apy: '0'
}
Example #19
Source File: requests.ts    From polkabtc-ui with Apache License 2.0 5 votes vote down vote up
// TODO: move functions to lib

/**
 * Converts an IssueRequest object retrieved from the parachain
 * to a UI IssueRequest object
 *
 * @param id H256, the key of the IssueRequest object in the parachain map storage object
 * @param parachainIssueRequest ParachainIssueRequest
 * @param parachainHeight parachainHeight data (queried from the parachain)
 * @param issuePeriod issuePeriod data (queried from the parachain)
 * @param requiredBtcConfirmations requiredBtcConfirmations data (queried from the parachain)
 */

async function parachainToUIIssueRequest(
  id: H256,
  parachainIssueRequest: ParachainIssueRequest,
  parachainHeight?: number,
  issuePeriod?: number,
  requiredBtcConfirmations?: number,
  requiredParachainConfirmations?: number
): Promise<IssueRequest> {
  if (!parachainHeight || !issuePeriod || !requiredBtcConfirmations || !requiredParachainConfirmations) {
    [parachainHeight, issuePeriod, requiredBtcConfirmations, requiredParachainConfirmations] = await Promise.all([
      window.polkaBTC.system.getCurrentBlockNumber(),
      window.polkaBTC.issue.getIssuePeriod(),
      window.polkaBTC.btcRelay.getStableBitcoinConfirmations(),
      window.polkaBTC.btcRelay.getStableParachainConfirmations()
    ]);
  }
  const amountPolkaBTC = satToBTC(parachainIssueRequest.amount.toString());
  const fee = satToBTC(parachainIssueRequest.fee.toString());
  const status = computeIssueRequestStatus(
    parachainIssueRequest.status.isCompleted,
    parachainIssueRequest.status.isCancelled,
    parachainIssueRequest.opentime.toNumber(),
    parachainHeight,
    issuePeriod,
    requiredBtcConfirmations,
    requiredParachainConfirmations
  );
  return {
    id: stripHexPrefix(id.toString()),
    requestedAmountPolkaBTC: amountPolkaBTC,
    timestamp: formatDateTimePrecise(new Date(Date.now())),
    creation: parachainIssueRequest.opentime.toString(),
    vaultBTCAddress: parachainIssueRequest.btc_address,
    vaultDOTAddress: parachainIssueRequest.vault.toString(),
    userDOTAddress: parachainIssueRequest.requester.toString(),
    btcTxId: '',
    fee,
    amountBTC: new Big(amountPolkaBTC).add(fee).toString(),
    griefingCollateral: planckToDOT(parachainIssueRequest.griefing_collateral.toString()),
    confirmations: 0,
    status,
    refundBtcAddress: '',
    refundAmountBtc: '',
    issuedAmountBtc: '',
    btcAmountSubmittedByUser: ''
  };
}
Example #20
Source File: requests.ts    From polkabtc-ui with Apache License 2.0 5 votes vote down vote up
/**
 * Converts an RedeemRequest object retrieved from the parachain
 * to a UI IssueRequest object
 * @param id H256, the key of the IssueRequest object in the parachain map storage object
 * @param parachainIssueRequest ParachainIssueRequest
 * @param parachainHeight parachainHeight data (queried from the parachain)
 * @param redeemPeriod redeemPeriod data (queried from the parachain)
 * @param requiredBtcConfirmations requiredBtcConfirmations data (queried from the parachain)
 */

async function parachainToUIRedeemRequest(
  id: H256,
  parachainRedeemRequest?: ParachainRedeemRequest,
  parachainHeight?: number,
  redeemPeriod?: number,
  requiredBtcConfirmations?: number,
  requiredParachainConfirmations?: number
): Promise<RedeemRequest> {
  if (
    !parachainRedeemRequest ||
    !parachainHeight ||
    !redeemPeriod ||
    !requiredBtcConfirmations ||
    !requiredParachainConfirmations
  ) {
    [
      parachainRedeemRequest,
      parachainHeight,
      redeemPeriod,
      requiredBtcConfirmations,
      requiredParachainConfirmations
    ] = await Promise.all([
      window.polkaBTC.redeem.getRequestById(id),
      window.polkaBTC.system.getCurrentBlockNumber(),
      window.polkaBTC.redeem.getRedeemPeriod(),
      window.polkaBTC.btcRelay.getStableBitcoinConfirmations(),
      window.polkaBTC.btcRelay.getStableParachainConfirmations()
    ]);
  }
  const amountBTC = satToBTC(parachainRedeemRequest.amount_btc.toString());
  const fee = satToBTC(parachainRedeemRequest.fee.toString());
  const amountPolkaBTC = new Big(amountBTC).add(new Big(fee)).toString();
  const status = computeRedeemRequestStatus(
    parachainRedeemRequest.status.isCompleted,
    parachainRedeemRequest.status.isRetried,
    parachainRedeemRequest.status.isReimbursed,
    parachainRedeemRequest.opentime.toNumber(),
    parachainHeight,
    redeemPeriod,
    requiredBtcConfirmations,
    requiredParachainConfirmations
  );
  return {
    id: stripHexPrefix(id.toString()),
    amountPolkaBTC,
    amountBTC,
    timestamp: formatDateTimePrecise(new Date(Number(Date.now()))),
    creation: parachainRedeemRequest.opentime.toString(),
    userBTCAddress: parachainRedeemRequest.btc_address,
    userDOTAddress: parachainRedeemRequest.redeemer.toString(),
    vaultDOTAddress: parachainRedeemRequest.vault.toString(),
    btcTxId: '',
    fee,
    btcTransferFee: '0', // FIXME if necessary - not sure this is actually going to be used anywhere
    confirmations: 0,
    status
  };
}
Example #21
Source File: index.tsx    From interbtc-ui with Apache License 2.0 4 votes vote down vote up
ReplaceTable = ({ vaultAddress }: Props): JSX.Element => {
  const { t } = useTranslation();
  const { bridgeLoaded } = useSelector((state: StoreType) => state.general);

  const vaultId = window.bridge?.api.createType(ACCOUNT_ID_TYPE_NAME, vaultAddress);
  const {
    isIdle: replaceRequestsIdle,
    isLoading: replaceRequestsLoading,
    data: replaceRequests,
    error: replaceRequestsError
  } = useQuery<Map<H256, ReplaceRequestExt>, Error>(
    [GENERIC_FETCHER, 'replace', 'mapReplaceRequests', vaultId],
    genericFetcher<Map<H256, ReplaceRequestExt>>(),
    {
      enabled: !!bridgeLoaded,
      refetchInterval: 10000
    }
  );
  useErrorHandler(replaceRequestsError);

  const columns = React.useMemo(
    () => [
      {
        Header: 'ID',
        accessor: 'id',
        classNames: ['text-center'],
        Cell: function FormattedCell({ value }: { value: H256 }) {
          return <>{stripHexPrefix(value.toString())}</>;
        }
      },
      {
        Header: t('vault.creation_block'),
        accessor: 'btcHeight',
        classNames: ['text-center']
      },
      {
        Header: t('vault.old_vault'),
        accessor: 'oldVault',
        classNames: ['text-center'],
        Cell: function FormattedCell({ value }: { value: InterbtcPrimitivesVaultId }) {
          return <>{shortAddress(value.accountId.toString())}</>;
        }
      },
      {
        Header: t('vault.new_vault'),
        accessor: 'newVault',
        classNames: ['text-center'],
        Cell: function FormattedCell({ value }: { value: InterbtcPrimitivesVaultId }) {
          return <>{shortAddress(value.accountId.toString())}</>;
        }
      },
      {
        Header: t('btc_address'),
        accessor: 'btcAddress',
        classNames: ['text-center'],
        Cell: function FormattedCell({ value }: { value: string }) {
          return <>{shortAddress(value)}</>;
        }
      },
      {
        Header: WRAPPED_TOKEN_SYMBOL,
        accessor: 'amount',
        classNames: ['text-right'],
        Cell: function FormattedCell({ value }: { value: MonetaryAmount<WrappedCurrency, BitcoinUnit> }) {
          return <>{displayMonetaryAmount(value)}</>;
        }
      },
      {
        Header: t('griefing_collateral'),
        accessor: 'collateral',
        classNames: ['text-right'],
        Cell: function FormattedCell({ value }: { value: MonetaryAmount<Currency<CollateralUnit>, CollateralUnit> }) {
          return <>{displayMonetaryAmount(value)}</>;
        }
      },
      {
        Header: t('status'),
        accessor: 'status',
        classNames: ['text-center'],
        Cell: function FormattedCell({ value }: { value: ReplaceRequestStatus }) {
          let label;
          if (value.isPending) {
            label = t('pending');
          } else if (value.isCompleted) {
            label = t('completed');
          } else if (value.isCancelled) {
            label = t('cancelled');
          } else {
            label = t('loading_ellipsis');
          }
          return <>{label}</>;
        }
      }
    ],
    [t]
  );

  const data = replaceRequests
    ? [...replaceRequests.entries()].map(([key, value]) => ({
        id: key,
        ...value
      }))
    : [];
  const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = useTable({
    columns,
    data
  });

  if (replaceRequestsIdle || replaceRequestsLoading) {
    return <PrimaryColorEllipsisLoader />;
  }
  if (replaceRequests === undefined) {
    throw new Error('Something went wrong!');
  }

  return (
    <InterlayTableContainer className={clsx('space-y-6', 'container', 'mx-auto')}>
      <SectionTitle>{t('vault.replace_requests')}</SectionTitle>
      <InterlayTable {...getTableProps()}>
        <InterlayThead>
          {headerGroups.map((headerGroup) => (
            // eslint-disable-next-line react/jsx-key
            <InterlayTr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                // eslint-disable-next-line react/jsx-key
                <InterlayTh
                  {...column.getHeaderProps([
                    {
                      className: clsx(column.classNames),
                      style: column.style
                    }
                  ])}
                >
                  {column.render('Header')}
                </InterlayTh>
              ))}
            </InterlayTr>
          ))}
        </InterlayThead>
        <InterlayTbody {...getTableBodyProps()}>
          {rows.map((row) => {
            prepareRow(row);

            return (
              // eslint-disable-next-line react/jsx-key
              <InterlayTr {...row.getRowProps()}>
                {row.cells.map((cell) => {
                  return (
                    // eslint-disable-next-line react/jsx-key
                    <InterlayTd
                      {...cell.getCellProps([
                        {
                          className: clsx(cell.column.classNames),
                          style: cell.column.style
                        }
                      ])}
                    >
                      {cell.render('Cell')}
                    </InterlayTd>
                  );
                })}
              </InterlayTr>
            );
          })}
        </InterlayTbody>
      </InterlayTable>
    </InterlayTableContainer>
  );
}