Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fetch redemption details #561

Merged
merged 18 commits into from
Jul 11, 2023
Merged

Fetch redemption details #561

merged 18 commits into from
Jul 11, 2023

Conversation

r-czajkowski
Copy link
Collaborator

@r-czajkowski r-czajkowski commented Jul 4, 2023

This PR adds support for fetching the redemption details data from the chain. Based on that data we render different states of the unminting process on the Redemption Details page.

Main changes:

Add new methods to the TBTC interface from threshold-ts lib

Add methods that fetch the redemption request and redemption-related events. Here we also noticed a bug in the ethers.js lib- the ethers.js lib encodes the bytesX param in the wrong way. It uses the left-padded rule but based on the Solidity docs it should be a sequence of bytes in X padded with trailing zero-bytes to a length of 32 bytes(right-padded). See https://docs.soliditylang.org/en/v0.8.17/abi-spec.html#formal-specification-of-the-encoding
Consider this wallet public key hash
0x03B74D6893AD46DFDD01B9E0E3B3385F4FCE2D1E:

  • ethers.js returns
    0x00000000000000000000000003b74d6893ad46dfdd01b9e0e3b3385f4fce2d1e
  • should be:
    0x03b74d6893ad46dfdd01b9e0e3b3385f4fce2d1e000000000000000000000000

In that case, in methods that fetch the past events by indexed param which has bytesX type(RedemptionsCompleted, RedemptionRequested, RedemptionTimedOut) we build the filter topics manually.

Hook that fetches the redemption details

This hook fetches the redemption request details based on the:

  • redemption requested tx hash- We also need to find an event by
    transaction hash because it's possible that there can be multiple
    RedemptionRequest events with the same redemption key but created at
    different times eg:
    • redemption X requested,

    • redemption X was handled successfully and the redemption X was
      removed from pendingRedemptions map,

    • the same wallet is still in live state and can handle the
      redemption request with the same walletPubKeyHash and
      redeemerOutputScript pair,

    • now 2 RedemptionRequested events exist with the same redemption
      key(the same walletPubKeyHash and redeemerOutputScript pair).

      In that case, we must know exactly which redemption request we
      want to fetch.

  • wallet public key hash- we need to find RedemptionRequested event by
    wallet public key hash to get all necessary data and make sure that
    the request actually happened. It's also used to build the redemption key,
  • redeemer- We need redeemer address as well to reduce the number of
    records- any user can request redemption for the same wallet.
  • redeemer output script- we need this param to build the redemption key
    and find the Bitcoin transfer for this redeemer output script.

Hook that fetches the block details such as timestamp

We need timestamps for a given block umber to calculate the total time it took to complete a redemption or how long a redemption request takes.

TODO(probably address in separate PRs):

Screenshots

Pending Redemption:
obraz

Completed Redemption:
obraz

Add `getBitcoinTransaction` method. To display the redemption details we
need to fetch the Bitcoin transaction to find whether the redemption
request was already handled successfully- meaning there was a Bitcoin
transfer to a given redeemer output script.
Add `buildRedemptionKey` method- builds the redemption key required to
refer a redemption request. Redemption key built as
`keccak256(keccak256(redeemerOutputScript) | walletPubKeyHash)`.
To fetch the redemption details data we need query events to find the
redemption request and verify whether the redemption was handled
successfully or timed out.

Here we also noticed a bug in the `ethers.js` lib- the `ethers.js` lib
encodes the `bytesX` param in the wrong way. It uses the left-padded
rule but based on the Solidity docs it should be a sequence of bytes in
X padded with trailing zero-bytes to a length of 32 bytes(right-padded).
See
https://docs.soliditylang.org/en/v0.8.17/abi-spec.html#formal-specification-of-the-encoding
Consider this wallet public key hash
`0x03B74D6893AD46DFDD01B9E0E3B3385F4FCE2D1E`:
- `ethers.js` returns
  `0x00000000000000000000000003b74d6893ad46dfdd01b9e0e3b3385f4fce2d1e`
- should be:
  `0x03b74d6893ad46dfdd01b9e0e3b3385f4fce2d1e000000000000000000000000`

In that case, in methods that fetch the past events by indexed param
which has `bytesX` type(`RedemptionsCompleted`, `RedemptionRequested`,
`RedemptionTimedOut`) we build the filter topics manually.
This hook fetches the redemption request details based on the:
- redemption requested tx hash-  We also need to find an event by
  transaction hash because it's possible that there can be multiple
  `RedemptionRequest` events with the same redemption key but created at
  different times eg:
    - redemption X requested,
    - redemption X was handled successfully and the redemption X was
      removed from `pendingRedemptions` map,
    - the same wallet is still in `live` state and can handle the
      redemption request with the same `walletPubKeyHash` and
      `redeemerOutputScript` pair,
    - now 2 `RedemptionRequested` events exist with the same redemption
      key(the same `walletPubKeyHash` and `redeemerOutputScript` pair).

      In that case, we must know exactly which redemption request we
      want to fetch.
- wallet public key hash- we need to find `RedemptionRequested` event by
  wallet public key hash to get all necessary data and make sure that
  the request actually happened,
- redeemer-  We need `redeemer` address as well to reduce the number of
  records- any user can request redemption for the same wallet.
- redeemer output script- we need this param to build the redemption key
  and find the Bitcoin transfer for this redeemer output script.
Compare correctly the `scriptPubKey` data from Bitcoin transacion
outputs with the redeemer output script from Ethereum event. The
redeemer otput script from the Ethereum event is prepended by the script
length encoded as a Bitcoin varint but the `scriptPubKey` is in a raw
format so we need to prefix the output script bytes buffer with 0x and
its own length.

Here we also hardcoded data in the `UnmintDetails` component for a
redemption that was already handled successfully- for testing purposes.
Display the redemption details data with real on-chain data. Based on
that data we render different states of the unminting process.
@github-actions
Copy link

github-actions bot commented Jul 4, 2023

Copy link
Contributor

@michalsmiarowski michalsmiarowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments to look at before the merge.

Overall looks great 💪 Love how earch step in the useFetchRedemptionDetails hook is commencted ❤️

src/hooks/tbtc/useFetchRedemptionDetails.ts Outdated Show resolved Hide resolved
src/hooks/tbtc/useFetchRedemptionDetails.ts Outdated Show resolved Hide resolved
src/hooks/tbtc/useFetchRedemptionDetails.ts Outdated Show resolved Hide resolved
src/hooks/tbtc/useFetchRedemptionDetails.ts Outdated Show resolved Hide resolved
src/hooks/tbtc/useFetchRedemptionDetails.ts Outdated Show resolved Hide resolved
src/threshold-ts/tbtc/index.ts Outdated Show resolved Hide resolved
src/threshold-ts/tbtc/index.ts Show resolved Hide resolved
src/threshold-ts/tbtc/index.ts Show resolved Hide resolved
src/hooks/tbtc/useFetchRedemptionDetails.ts Show resolved Hide resolved
src/hooks/tbtc/useFetchRedemptionDetails.ts Outdated Show resolved Hide resolved
We should assign useColorModeValue("white", "brand.800") to the variable
on top of the component.
BTC address on success page redirects to the etherscan instead of
blockstream. Here we add `chain="bitcoin"` prop to fix this bug.
We should assign `event.ergs?.treasuryFee` instead of
`event.ergs?.redeemer` to the `treasuryFee`.
Mention in comments that the current code is a workaround and we should
use `getContractPastEvents` to fetch events one we provide a fix in the
`ethers.js` lib. The `ethers.js` lib encodes the `bytesX` param in the
wrong way.
Move function that prefixes the output script with `0x` and its own
length to `threshold-ts` lib utils.
@github-actions
Copy link

github-actions bot commented Jul 7, 2023

Copy link
Contributor

@michalsmiarowski michalsmiarowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left one comment to point out the TODO but overall looking good. I'm ready to merge it

src/hooks/tbtc/useFetchRedemptionDetails.ts Show resolved Hide resolved
Copy link
Contributor

@michalsmiarowski michalsmiarowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🔥

@michalsmiarowski michalsmiarowski merged commit 40a99f8 into main Jul 11, 2023
4 of 5 checks passed
@michalsmiarowski michalsmiarowski deleted the fetch-redemption-details branch July 11, 2023 14:28
@r-czajkowski r-czajkowski self-assigned this Jul 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants