Skip to content

Commit

Permalink
feat: update use endpoints hook (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
Polybius93 authored Mar 14, 2024
1 parent 7f67053 commit ebedf9f
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 64 deletions.
37 changes: 14 additions & 23 deletions src/app/hooks/use-bitcoin.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { useEffect, useState } from 'react';

import { BitcoinNetwork, regtest } from '@models/bitcoin-network';
import { BitcoinNetwork } from '@models/bitcoin-network';
import { BitcoinError } from '@models/error-types';
import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
import { hex } from '@scure/base';
import * as btc from '@scure/btc-signer';

import { useEndpoints } from './use-endpoints';

const networkModes = ['mainnet', 'testnet'] as const;
const networkModes = ['mainnet', 'testnet', 'regtest'] as const;

type NetworkModes = (typeof networkModes)[number];

// type BitcoinTestnetModes = 'testnet' | 'regtest' | 'signet';

// type BitcoinNetworkModes = NetworkModes | BitcoinTestnetModes;

declare enum SignatureHash {
ALL = 1,
NONE = 2,
Expand All @@ -27,7 +23,7 @@ declare enum SignatureHash {
interface SignPsbtRequestParams {
hex: string;
allowedSighash?: SignatureHash[];
signAtIndex?: number | number[];
signAtIndex?: number | number[]; // default is all inputs
network?: NetworkModes; // default is user's current network
account?: number; // default is user's current account
broadcast?: boolean; // default is false - finalize/broadcast tx
Expand Down Expand Up @@ -94,9 +90,8 @@ export interface UseBitcoinReturnType {
}

export function useBitcoin(): UseBitcoinReturnType {
const { attestorAPIURLs, bitcoinBlockchainAPIURL } = useEndpoints();
const { attestorAPIURLs, bitcoinNetwork, bitcoinBlockchainAPIURL } = useEndpoints();
const [bitcoinPrice, setBitcoinPrice] = useState(0);
const [btcNetwork, setBTCNetwork] = useState<BitcoinNetwork>(regtest);

useEffect(() => {
const getBitcoinPrice = async () => {
Expand All @@ -121,7 +116,7 @@ export function useBitcoin(): UseBitcoinReturnType {
);
const allUTXOs = await response.json();
const userPublicKey = hexToBytes(bitcoinNativeSegwitAddress.publicKey);
const spend = btc.p2wpkh(userPublicKey, regtest);
const spend = btc.p2wpkh(userPublicKey, bitcoinNetwork);

const utxos = await Promise.all(
allUTXOs.map(async (utxo: UTXO) => {
Expand Down Expand Up @@ -198,7 +193,6 @@ export function useBitcoin(): UseBitcoinReturnType {
uuid: string,
userNativeSegwitAddress: string
): Promise<void> {
setBTCNetwork(regtest);
const createPSBTURLs = attestorAPIURLs.map(url => `${url}/app/create-psbt-event`);
const requests = createPSBTURLs.map(async url => {
fetch(url, {

Check warning on line 198 in src/app/hooks/use-bitcoin.ts

View workflow job for this annotation

GitHub Actions / lint-eslint

Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator
Expand Down Expand Up @@ -238,11 +232,9 @@ export function useBitcoin(): UseBitcoinReturnType {
return closingPSBT;
}

async function signPSBT(psbt: Uint8Array, shouldBroadcast: boolean): Promise<string> {
async function signPSBT(psbt: Uint8Array): Promise<string> {
const requestParams: SignPsbtRequestParams = {
hex: bytesToHex(psbt),
signAtIndex: [0],
broadcast: shouldBroadcast,
};
const result = await window.btc.request('signPsbt', requestParams);
return result.result.hex;
Expand All @@ -254,15 +246,15 @@ export function useBitcoin(): UseBitcoinReturnType {
utxos: any[],
btcAmount: number,
btcNetwork: BitcoinNetwork
): Promise<{ fundingTransactionHex: string; fundingTransactionID: string }> {
): Promise<string> {
const fundingTransaction = createFundingTransaction(
multisigAddress,
userChangeAddress,
utxos,
btcAmount,
btcNetwork
);
const fundingTransactionHex = await signPSBT(fundingTransaction, false);
const fundingTransactionHex = await signPSBT(fundingTransaction);
const transaction = btc.Transaction.fromPSBT(hexToBytes(fundingTransactionHex));
transaction.finalize();

Expand All @@ -273,7 +265,7 @@ export function useBitcoin(): UseBitcoinReturnType {
}).then(async response => {
fundingTransactionID = await response.text();
});
return { fundingTransactionHex, fundingTransactionID };
return fundingTransactionID;
}

async function handleClosingTransaction(
Expand All @@ -291,7 +283,7 @@ export function useBitcoin(): UseBitcoinReturnType {
btcAmount,
btcNetwork
);
const closingTransactionHex = await signPSBT(closingTransaction, false);
const closingTransactionHex = await signPSBT(closingTransaction);

await sendPSBT(closingTransactionHex, uuid, userAddress);
return closingTransactionHex;
Expand All @@ -316,17 +308,16 @@ export function useBitcoin(): UseBitcoinReturnType {
const { multisigTransaction, multisigAddress } = createMultisigTransactionAndAddress(
hex.decode(userPublicKey),
hex.decode(attestorPublicKey),
btcNetwork
bitcoinNetwork
);

const { fundingTransactionHex, fundingTransactionID } = await handleFundingTransaction(
const fundingTransactionID = await handleFundingTransaction(
multisigAddress,
userNativeSegwitAddress,
userUTXOs,
btcAmount,
btcNetwork
bitcoinNetwork
);
console.log('fundingTransactionHex', fundingTransactionHex);

return { fundingTransactionID, multisigTransaction, userNativeSegwitAddress, btcAmount };
}
Expand All @@ -347,7 +338,7 @@ export function useBitcoin(): UseBitcoinReturnType {
userNativeSegwitAddress,
uuid,
btcAmount,
btcNetwork
bitcoinNetwork
);
}

Expand Down
42 changes: 27 additions & 15 deletions src/app/hooks/use-endpoints.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';

import { BitcoinNetwork, bitcoin, regtest, testnet } from '@models/bitcoin-network';
import { EthereumNetwork } from '@models/network';
import { RootState } from '@store/index';

Expand All @@ -9,6 +10,7 @@ interface NetworkEndpoints {
ethereumExplorerAPIURL: string;
bitcoinExplorerAPIURL: string;
bitcoinBlockchainAPIURL: string;
bitcoinNetwork: BitcoinNetwork;
}

export function useEndpoints(): NetworkEndpoints {
Expand All @@ -18,6 +20,7 @@ export function useEndpoints(): NetworkEndpoints {
const [ethereumExplorerAPIURL, setEthereumExplorerAPIURL] = useState<string>('');
const [bitcoinExplorerAPIURL, setBitcoinExplorerAPIURL] = useState<string>('');
const [bitcoinBlockchainAPIURL, setBitcoinBlockchainAPIURL] = useState<string>('');
const [bitcoinNetwork, setBitcoinNetwork] = useState<BitcoinNetwork>(regtest);

useEffect(() => {
if (!network) return;
Expand All @@ -33,42 +36,50 @@ export function useEndpoints(): NetworkEndpoints {
setEthereumExplorerAPIURL(ethereumExplorerAPIURL);
setBitcoinExplorerAPIURL(bitcoinExplorerAPIURL);
setBitcoinBlockchainAPIURL(bitcoinBlockchainAPIURL);
setBitcoinNetwork(bitcoinNetwork);
}, [network]);

function getEndpoints(): NetworkEndpoints {
const attestorAPIURLs: string[] = import.meta.env.VITE_ATTESTOR_API_URLS.split(',');

const bitcoinNetworkName = import.meta.env.VITE_BITCOIN_NETWORK;
let bitcoinNetwork;

switch (bitcoinNetworkName) {
case 'mainnet':
bitcoinNetwork = bitcoin;
break;
case 'testnet':
bitcoinNetwork = testnet;
break;
default:
bitcoinNetwork = regtest;
}

switch (network?.id) {
case EthereumNetwork.Sepolia:
return {
attestorAPIURLs: [
'https://devnet.dlc.link/attestor-1',
'https://devnet.dlc.link/attestor-2',
'https://devnet.dlc.link/attestor-3',
],
attestorAPIURLs,
ethereumExplorerAPIURL: 'https://sepolia.etherscan.io/tx/',
bitcoinExplorerAPIURL: 'http://devnet.dlc.link/electrs/tx/',
bitcoinBlockchainAPIURL: 'https://devnet.dlc.link/electrs',
bitcoinNetwork,
};
case EthereumNetwork.Goerli:
return {
attestorAPIURLs: [
'http://localhost:8811',
'http://localhost:8812',
'http://localhost:8813',
],
attestorAPIURLs,
ethereumExplorerAPIURL: 'https://goerli.etherscan.io/tx/',
bitcoinExplorerAPIURL: 'https://blockstream.info/testnet/tx/',
bitcoinBlockchainAPIURL: 'https://devnet.dlc.link/electrs',
bitcoinNetwork,
};
case EthereumNetwork.X1Testnet:
return {
attestorAPIURLs: [
'http://localhost:8811',
'http://localhost:8812',
'http://localhost:8813',
],
attestorAPIURLs,
ethereumExplorerAPIURL: 'https://www.oklink.com/x1-test/tx/',
bitcoinExplorerAPIURL: 'http://devnet.dlc.link/electrs/tx/',
bitcoinBlockchainAPIURL: 'https://devnet.dlc.link/electrs',
bitcoinNetwork,
};
default:
throw new Error(`Unsupported network: ${network?.name}`);
Expand All @@ -79,5 +90,6 @@ export function useEndpoints(): NetworkEndpoints {
ethereumExplorerAPIURL,
bitcoinExplorerAPIURL,
bitcoinBlockchainAPIURL,
bitcoinNetwork,
};
}
53 changes: 27 additions & 26 deletions src/shared/models/bitcoin-network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ export interface BitcoinNetwork {
versionBytes: number;
}

// export const bitcoin: BitcoinNetwork = {
// messagePrefix: '\x18Bitcoin Signed Message:\n',
// bech32: 'bc',
// bip32: {
// public: 0x0488b21e,
// private: 0x0488ade4,
// },
// pubKeyHash: 0x00,
// scriptHash: 0x05,
// wif: 0x80,
// bytes: 21,
// versionBytes: 1,
// };
export const bitcoin: BitcoinNetwork = {
messagePrefix: '\x18Bitcoin Signed Message:\n',
bech32: 'bc',
bip32: {
public: 0x0488b21e,
private: 0x0488ade4,
},
pubKeyHash: 0x00,
scriptHash: 0x05,
wif: 0x80,
bytes: 21,
versionBytes: 1,
};

export const regtest: BitcoinNetwork = {
messagePrefix: '\x18Bitcoin Signed Message:\n',
Expand All @@ -41,16 +41,17 @@ export const regtest: BitcoinNetwork = {
bytes: 21,
versionBytes: 1,
};
// export const testnet: BitcoinNetwork = {
// messagePrefix: '\x18Bitcoin Signed Message:\n',
// bech32: 'tb',
// bip32: {
// public: 0x043587cf,
// private: 0x04358394,
// },
// pubKeyHash: 0x6f,
// scriptHash: 0xc4,
// wif: 0xef,
// bytes: 21,
// versionBytes: 1,
// };

export const testnet: BitcoinNetwork = {
messagePrefix: '\x18Bitcoin Signed Message:\n',
bech32: 'tb',
bip32: {
public: 0x043587cf,
private: 0x04358394,
},
pubKeyHash: 0x6f,
scriptHash: 0xc4,
wif: 0xef,
bytes: 21,
versionBytes: 1,
};

0 comments on commit ebedf9f

Please sign in to comment.