Skip to content

Commit

Permalink
Mempool client fix (#34)
Browse files Browse the repository at this point in the history
* update mempool client endpoint

* Add support for multiple public client options (mempool or blockstream)

* fix: avoid unnecessary re-instantiation of client
  • Loading branch information
bucko13 authored Mar 5, 2024
1 parent 80ddf86 commit b4e349c
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 36 deletions.
5 changes: 5 additions & 0 deletions .changeset/clean-lamps-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@caravan/coordinator": minor
---

Add support for different public client options (mempool or blockstream).
5 changes: 5 additions & 0 deletions .changeset/tricky-stingrays-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@caravan/clients": patch
---

Update mempool client host
4 changes: 3 additions & 1 deletion apps/coordinator/src/actions/clientActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export const getBlockchainClientFromStore = async () => {
const { network } = getState().settings;
const { client } = getState();
if (!client) return;
if (client.blockchainClient?.type === client.type)
return client.blockchainClient;
let clientType: ClientType;

switch (client.type) {
Expand All @@ -42,7 +44,7 @@ export const getBlockchainClientFromStore = async () => {
client,
type: clientType,
network,
throttled: true,
throttled: client.type === ClientType.BLOCKSTREAM,
});
dispatch({ type: SET_BLOCKCHAIN_CLIENT, value: blockchainClient });
return blockchainClient;
Expand Down
28 changes: 14 additions & 14 deletions apps/coordinator/src/components/ClientPicker/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
FormControl,
Radio,
RadioGroup,
FormHelperText,
} from "@mui/material";
import { ClientType } from "@caravan/clients";

// Components

Expand Down Expand Up @@ -127,13 +127,22 @@ const ClientPicker = ({
<FormControl component="fieldset">
<RadioGroup>
<FormControlLabel
id="public"
id={ClientType.MEMPOOL}
control={<Radio color="primary" />}
name="clientType"
value="public"
label={<strong>Public</strong>}
value={ClientType.MEMPOOL}
label={<strong>Mempool.space</strong>}
onChange={handleTypeChange}
checked={client.type === "public"}
checked={client.type === ClientType.MEMPOOL}
/>
<FormControlLabel
id={ClientType.BLOCKSTREAM}
control={<Radio color="primary" />}
name="clientType"
value={ClientType.BLOCKSTREAM}
label={<strong>Blockstream.info</strong>}
onChange={handleTypeChange}
checked={client.type === ClientType.BLOCKSTREAM}
/>
<FormControlLabel
id="private"
Expand All @@ -145,15 +154,6 @@ const ClientPicker = ({
checked={client.type === "private"}
/>
</RadioGroup>
{client.type === "public" && (
<FormHelperText>
{"'Public' uses the "}
<code>{blockchainClient?.type}</code>
{" API. Switch to private to use a "}
<code>bitcoind</code>
{" node."}
</FormHelperText>
)}
{client.type === "private" && (
<PrivateClientSettings
handleUrlChange={(event) => handleUrlChange(event)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ export const WalletDescriptorImporter = () => {
try {
const config = await getWalletFromDescriptor(descriptor, network);
const checksum = await getChecksum(descriptor);
console.log(config);
dispatch(updateWalletUuidAction(checksum));
setWalletConfig(config);
} catch (e) {
Expand Down
10 changes: 8 additions & 2 deletions apps/coordinator/src/components/Wallet/WalletGenerator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
Box,
} from "@mui/material";
import AccountCircleIcon from "@mui/icons-material/AccountCircle";

import { ClientType } from "@caravan/clients";
import ClientPicker from "../ClientPicker";
import ConfirmWallet from "./ConfirmWallet";
import RegisterWallet from "./RegisterWallet";
Expand Down Expand Up @@ -460,7 +460,13 @@ class WalletGenerator extends React.Component {
variant="contained"
color="primary"
onClick={this.generate}
disabled={client.type !== "public" && !connectSuccess}
disabled={
![
"public",
ClientType.MEMPOOL,
ClientType.BLOCKSTREAM,
].includes(client.type) && !connectSuccess
}
>
Confirm
</Button>
Expand Down
12 changes: 8 additions & 4 deletions apps/coordinator/src/components/Wallet/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
validateExtendedPublicKey,
} from "@caravan/bitcoin";
import { Box, Button, FormHelperText, Grid } from "@mui/material";
import { ClientType } from "@caravan/clients";
import { downloadFile } from "../../utils";
import {
resetWallet as resetWalletAction,
Expand Down Expand Up @@ -97,10 +98,13 @@ class CreateWallet extends React.Component {
}

if (config.client) {
const clientProperties =
config.client.type === "public"
? ["type"]
: ["type", "url", "username"];
const clientProperties = [
"public",
ClientType.MEMPOOL,
ClientType.BLOCKSTREAM,
].includes(config.client.type)
? ["type"]
: ["type", "url", "username"];
const validClient = CreateWallet.validateProperties(
config,
clientProperties,
Expand Down
2 changes: 1 addition & 1 deletion apps/coordinator/src/selectors/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const getClientDetails = (state) => {
}`;
}
return `{
"type": "public"
"type": "${state.client.type}"
}`;
};

Expand Down
26 changes: 18 additions & 8 deletions packages/caravan-clients/src/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ describe("BlockchainClient", () => {
type: ClientType.MEMPOOL,
network: Network.MAINNET,
});
expect(mempool.host).toEqual("https://mempool.space/api/v1");
expect(mempool.host).toEqual("https://unchained.mempool.space/api");
});

it("should set the testnet host for a public client", () => {
Expand All @@ -119,15 +119,15 @@ describe("BlockchainClient", () => {
type: ClientType.MEMPOOL,
network: Network.TESTNET,
});
expect(mempool.host).toEqual("https://mempool.space/testnet/api/v1");
expect(mempool.host).toEqual("https://unchained.mempool.space/testnet/api");
});

it("should set the signet host for a public client", () => {
const mempool = new BlockchainClient({
type: ClientType.MEMPOOL,
network: Network.SIGNET,
});
expect(mempool.host).toEqual("https://mempool.space/signet/api/v1");
expect(mempool.host).toEqual("https://unchained.mempool.space/signet/api");
expect(() => {
new BlockchainClient({
type: ClientType.BLOCKSTREAM,
Expand Down Expand Up @@ -482,8 +482,18 @@ describe("BlockchainClient", () => {

// Mock the response from the Get method
const mockUtxos: UTXO[] = [
{ txid: "txid1", vout: 0, value: 100, status: {confirmed: true, block_time: 21} },
{ txid: "txid2", vout: 1, value: 200, status: {confirmed: true, block_time: 42} },
{
txid: "txid1",
vout: 0,
value: 100,
status: { confirmed: true, block_time: 21 },
},
{
txid: "txid2",
vout: 1,
value: 200,
status: { confirmed: true, block_time: 42 },
},
];
const mockGet = jest.fn().mockResolvedValue(mockUtxos);

Expand All @@ -504,8 +514,8 @@ describe("BlockchainClient", () => {
// Verify the returned result
expect(result.utxos).toEqual(
await Promise.all(
mockUtxos.map((utxo: UTXO) => blockchainClient.formatUtxo(utxo))
)
mockUtxos.map((utxo: UTXO) => blockchainClient.formatUtxo(utxo)),
),
);
expect(result.balanceSats).toEqual(new BigNumber(300));
expect(result.addressKnown).toBe(true);
Expand Down Expand Up @@ -770,7 +780,7 @@ describe("BlockchainClient", () => {
);

// Verify the mock axios instance was called with the correct URL
expect(mockGet).toHaveBeenCalledWith("/fees/recommended");
expect(mockGet).toHaveBeenCalledWith("/v1/fees/recommended");
// Verify the returned fee estimate
expect(feeEstimate).toEqual(mockResponse[block]);
}
Expand Down
8 changes: 3 additions & 5 deletions packages/caravan-clients/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,13 @@ export class BlockchainClient extends ClientBase {
if (type === ClientType.BLOCKSTREAM) {
host = "https://blockstream.info";
} else if (type === ClientType.MEMPOOL) {
host = "https://mempool.space";
host = "https://unchained.mempool.space";
}
if (type !== ClientType.PRIVATE && network !== Network.MAINNET) {
host += `/${network}`;
}
if (type === ClientType.BLOCKSTREAM) {
if (type !== ClientType.PRIVATE) {
host += "/api";
} else if (type === ClientType.MEMPOOL) {
host += "/api/v1";
}
super(throttled, host);
this.network = network;
Expand Down Expand Up @@ -284,7 +282,7 @@ export class BlockchainClient extends ClientBase {
fees = await this.Get(`/fee-estimates`);
return fees[blocks];
case ClientType.MEMPOOL:
fees = await this.Get("/fees/recommended");
fees = await this.Get("/v1/fees/recommended");
if (blocks === 1) {
return fees.fastestFee;
} else if (blocks <= 3) {
Expand Down

0 comments on commit b4e349c

Please sign in to comment.