Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 27 additions & 20 deletions typescript/api-reference/classes/RedemptionsService.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Service exposing features related to tBTC v2 redemptions.

#### Defined in

[services/redemptions/redemptions-service.ts:47](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L47)
[services/redemptions/redemptions-service.ts:48](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L48)

## Properties

Expand All @@ -78,7 +78,7 @@ Gets cross-chain contracts for the given supported L2 chain.

#### Defined in

[services/redemptions/redemptions-service.ts:45](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L45)
[services/redemptions/redemptions-service.ts:46](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L46)

___

Expand All @@ -90,7 +90,7 @@ Bitcoin client handle.

#### Defined in

[services/redemptions/redemptions-service.ts:38](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L38)
[services/redemptions/redemptions-service.ts:39](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L39)

___

Expand All @@ -102,7 +102,7 @@ Handle to tBTC contracts.

#### Defined in

[services/redemptions/redemptions-service.ts:34](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L34)
[services/redemptions/redemptions-service.ts:35](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L35)

## Methods

Expand Down Expand Up @@ -133,7 +133,7 @@ An array of subarrays, where each subarray has a maximum length of `chunkSize`.

#### Defined in

[services/redemptions/redemptions-service.ts:580](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L580)
[services/redemptions/redemptions-service.ts:660](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L660)

___

Expand All @@ -160,7 +160,7 @@ Object containing:

#### Defined in

[services/redemptions/redemptions-service.ts:315](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L315)
[services/redemptions/redemptions-service.ts:316](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L316)

___

Expand All @@ -169,13 +169,20 @@ ___
▸ **determineValidRedemptionWallet**(`amount`, `potentialCandidateWallets`, `redeemerAddressOrScript?`): `Promise`\<[`RedemptionWallet`](../interfaces/RedemptionWallet.md)\>

Determines a valid wallet that can handle a redemption request.
Cross-checks API-provided wallet candidates against the current Bridge
state before accepting them. A candidate is accepted only if the on-chain
wallet is Live, its on-chain public key does not disagree with the API
public key, and its main UTXO matches the Bridge's main UTXO hash or can be
re-resolved from Bitcoin history. The spendable balance is capped to the
lower of the API balance and the on-chain main UTXO value minus pending
Bridge redemptions.

#### Parameters

| Name | Type | Description |
| :------ | :------ | :------ |
| `amount` | `BigNumber` | The amount to be redeemed in satoshi precision (1e8). |
| `potentialCandidateWallets` | [`SerializableWallet`](../interfaces/SerializableWallet.md)[] | Array of wallets that can handle the redemption request. The wallets must be in the Live state. |
| `potentialCandidateWallets` | [`SerializableWallet`](../interfaces/SerializableWallet.md)[] | Array of wallets that can handle the redemption request. |
| `redeemerAddressOrScript?` | `string` | Optional. Either a Bitcoin address (P2PKH, P2WPKH, P2SH, P2WSH) or a raw hex output script (with or without 0x prefix). When provided, the function checks for pending redemptions to avoid wallet collisions. - If the input matches /^(0x)?[0-9a-fA-F]+$/, it's treated as a raw hex output script and used directly. - Otherwise, it's treated as a Bitcoin address and converted to an output script. |

#### Returns
Expand All @@ -195,7 +202,7 @@ Throws an error if no valid redemption wallet exists for the given

#### Defined in

[services/redemptions/redemptions-service.ts:359](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L359)
[services/redemptions/redemptions-service.ts:367](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L367)

___

Expand All @@ -222,7 +229,7 @@ Promise holding the wallet main UTXO or undefined value.

#### Defined in

[services/redemptions/redemptions-service.ts:599](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L599)
[services/redemptions/redemptions-service.ts:679](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L679)

___

Expand All @@ -241,7 +248,7 @@ Array of wallet events.

#### Defined in

[services/redemptions/redemptions-service.ts:753](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L753)
[services/redemptions/redemptions-service.ts:833](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L833)

___

Expand All @@ -268,7 +275,7 @@ Promise with the wallet details needed to request a redemption.

#### Defined in

[services/redemptions/redemptions-service.ts:439](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L439)
[services/redemptions/redemptions-service.ts:519](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L519)

___

Expand All @@ -288,7 +295,7 @@ ___

#### Defined in

[services/redemptions/redemptions-service.ts:840](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L840)
[services/redemptions/redemptions-service.ts:920](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L920)

___

Expand All @@ -312,7 +319,7 @@ The output script of the given Bitcoin address.

#### Defined in

[services/redemptions/redemptions-service.ts:778](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L778)
[services/redemptions/redemptions-service.ts:858](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L858)

___

Expand Down Expand Up @@ -343,7 +350,7 @@ Throws an error if no redemption request exists for the given

#### Defined in

[services/redemptions/redemptions-service.ts:711](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L711)
[services/redemptions/redemptions-service.ts:791](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L791)

___

Expand Down Expand Up @@ -379,7 +386,7 @@ Throws an error if no wallet with sufficient funds can be found.

#### Defined in

[services/redemptions/redemptions-service.ts:244](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L244)
[services/redemptions/redemptions-service.ts:245](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L245)

___

Expand Down Expand Up @@ -409,7 +416,7 @@ Object containing:

#### Defined in

[services/redemptions/redemptions-service.ts:200](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L200)
[services/redemptions/redemptions-service.ts:201](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L201)

___

Expand Down Expand Up @@ -438,7 +445,7 @@ Object containing:

#### Defined in

[services/redemptions/redemptions-service.ts:84](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L84)
[services/redemptions/redemptions-service.ts:85](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L85)

___

Expand Down Expand Up @@ -470,7 +477,7 @@ Object containing:

#### Defined in

[services/redemptions/redemptions-service.ts:156](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L156)
[services/redemptions/redemptions-service.ts:157](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L157)

___

Expand All @@ -496,7 +503,7 @@ The resolved output script as a Hex object.

#### Defined in

[services/redemptions/redemptions-service.ts:808](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L808)
[services/redemptions/redemptions-service.ts:888](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L888)

___

Expand All @@ -520,4 +527,4 @@ once the loader is ready.

#### Defined in

[services/redemptions/redemptions-service.ts:65](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L65)
[services/redemptions/redemptions-service.ts:66](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/services/redemptions/redemptions-service.ts#L66)
17 changes: 16 additions & 1 deletion typescript/api-reference/enums/ApiUrl.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,27 @@
### Enumeration Members

- [TBTC\_EXPLORER](ApiUrl.md#tbtc_explorer)
- [THRESHOLD\_API](ApiUrl.md#threshold_api)

## Enumeration Members

### TBTC\_EXPLORER

• **TBTC\_EXPLORER** = ``"https://api.tbtcscan.com"``
• **TBTC\_EXPLORER** = ``"https://api.threshold.network"``

**`Deprecated`**

Use THRESHOLD_API.

#### Defined in

[lib/utils/api.ts:7](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/lib/utils/api.ts#L7)

___

### THRESHOLD\_API

• **THRESHOLD\_API** = ``"https://api.threshold.network"``

#### Defined in

Expand Down
2 changes: 1 addition & 1 deletion typescript/api-reference/enums/endpointUrl.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@

#### Defined in

[lib/utils/api.ts:7](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/lib/utils/api.ts#L7)
[lib/utils/api.ts:11](https://github.com/threshold-network/tbtc-v2/blob/main/typescript/src/lib/utils/api.ts#L11)
6 changes: 5 additions & 1 deletion typescript/src/lib/utils/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/* eslint-disable no-unused-vars */
export enum ApiUrl {
TBTC_EXPLORER = "https://api.tbtcscan.com",
THRESHOLD_API = "https://api.threshold.network",
/**
* @deprecated Use THRESHOLD_API.
*/
TBTC_EXPLORER = "https://api.threshold.network",
}

export enum endpointUrl {
Expand Down
98 changes: 89 additions & 9 deletions typescript/src/services/redemptions/redemptions-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import {
BitcoinAddressConverter,
BitcoinClient,
BitcoinHashUtils,
BitcoinNetwork,
BitcoinScriptUtils,
BitcoinTxHash,
Expand Down Expand Up @@ -337,9 +338,16 @@ export class RedemptionsService {

/**
* Determines a valid wallet that can handle a redemption request.
* Cross-checks API-provided wallet candidates against the current Bridge
* state before accepting them. A candidate is accepted only if the on-chain
* wallet is Live, its on-chain public key does not disagree with the API
* public key, and its main UTXO matches the Bridge's main UTXO hash or can be
* re-resolved from Bitcoin history. The spendable balance is capped to the
* lower of the API balance and the on-chain main UTXO value minus pending
* Bridge redemptions.
* @param amount The amount to be redeemed in satoshi precision (1e8).
* @param potentialCandidateWallets Array of wallets that can handle the
* redemption request. The wallets must be in the Live state.
* redemption request.
* @param redeemerAddressOrScript Optional. Either a Bitcoin address (P2PKH,
* P2WPKH, P2SH, P2WSH) or a raw hex output script (with or without
* 0x prefix). When provided, the function checks for pending
Expand Down Expand Up @@ -371,18 +379,41 @@ export class RedemptionsService {
)
}

const bitcoinNetwork = await this.bitcoinClient.getNetwork()

for (let index = 0; index < potentialCandidateWallets.length; index++) {
const serializableWallet = potentialCandidateWallets[index]
const {
walletBTCBalance: candidateBTCBalance,
walletBTCBalance: apiCandidateBTCBalance,
walletPublicKey: candidatePublicKey,
mainUtxo: candidateMainUtxo,
} = this.fromSerializableWallet(serializableWallet)

if (candidateBTCBalance.lt(amount)) {
const walletPublicKeyHash =
BitcoinHashUtils.computeHash160(candidatePublicKey)
const currentWallet = await this.tbtcContracts.bridge.wallets(
walletPublicKeyHash
)

if (!currentWallet || currentWallet.state !== WalletState.Live) {
console.debug(
`The wallet (${candidatePublicKey.toString()})` +
`cannot handle the redemption request. ` +
`Wallet is not in Live state ` +
`(wallet public key hash: ${walletPublicKeyHash.toString()}). ` +
`Continue the loop execution to the next wallet...`
)
continue
}

// Missing on-chain public key is tolerated to avoid turning a registry
// data issue into a candidate rejection. A disagreement is unsafe.
if (
currentWallet.walletPublicKey &&
!currentWallet.walletPublicKey.equals(candidatePublicKey)
) {
console.debug(
`The wallet public key returned by the redemption wallet API ` +
`does not match the on-chain wallet public key ` +
`(wallet public key hash: ${walletPublicKeyHash.toString()}). ` +
`Continue the loop execution to the next wallet...`
)
continue
Expand All @@ -407,11 +438,60 @@ export class RedemptionsService {
continue
}
}

let currentMainUtxo = candidateMainUtxo
const candidateMainUtxoHash =
this.tbtcContracts.bridge.buildUtxoHash(candidateMainUtxo)

if (!currentWallet.mainUtxoHash.equals(candidateMainUtxoHash)) {
console.debug(
`The wallet main UTXO returned by the redemption wallet API is stale ` +
`(wallet public key hash: ${walletPublicKeyHash.toString()}). ` +
`Trying to resolve the current wallet main UTXO...`
)

const resolvedMainUtxo = await this.determineWalletMainUtxo(
walletPublicKeyHash,
bitcoinNetwork
)

if (!resolvedMainUtxo) {
console.debug(
`Could not resolve current main UTXO for wallet ` +
`${walletPublicKeyHash.toString()}. ` +
`Continue the loop execution to the next wallet...`
)
continue
}

currentMainUtxo = resolvedMainUtxo
}

const onChainCandidateBTCBalance = currentMainUtxo.value.gt(
currentWallet.pendingRedemptionsValue
)
? currentMainUtxo.value.sub(currentWallet.pendingRedemptionsValue)
: BigNumber.from(0)
const candidateBTCBalance = onChainCandidateBTCBalance.lt(
apiCandidateBTCBalance
)
? onChainCandidateBTCBalance
: apiCandidateBTCBalance

if (candidateBTCBalance.lt(amount)) {
console.debug(
`The wallet (${candidatePublicKey.toString()}) ` +
`cannot handle the redemption request. ` +
`Continue the loop execution to the next wallet...`
)
continue
}

walletPublicKey = candidatePublicKey
mainUtxo = candidateMainUtxo
mainUtxo = currentMainUtxo

console.debug(
`The wallet (${walletPublicKey.toString()})` +
`The wallet (${walletPublicKey.toString()}) ` +
`can handle the redemption request. ` +
`Stop the loop execution and proceed with the redemption...`
)
Expand Down Expand Up @@ -528,7 +608,7 @@ export class RedemptionsService {
})
} else {
console.debug(
`The wallet (${walletPublicKeyHash.toString()})` +
`The wallet (${walletPublicKeyHash.toString()}) ` +
`cannot handle the redemption request. ` +
`Continue the loop execution to the next wallet...`
)
Expand Down Expand Up @@ -760,7 +840,7 @@ export class RedemptionsService {
}

const response = await fetch(
`${ApiUrl.TBTC_EXPLORER}${endpointUrl.TBTC_REDEMPTION_WALLET}`
`${ApiUrl.THRESHOLD_API}${endpointUrl.TBTC_REDEMPTION_WALLET}`
)
if (!response.ok) {
throw new Error("Failed to fetch redemption wallet from server")
Expand Down
Loading
Loading