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

DLC flow updated to use blockstream API, added regtest #120

Draft
wants to merge 19 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
Binary file added .DS_Store
Binary file not shown.
6 changes: 6 additions & 0 deletions account/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ export async function restoreWalletWithAccounts(
id: index,
stxAddress: response.stxAddress,
btcAddress: response.btcAddress,
mainBtcAddress: response.mainBtcAddress,
mainBtcPublicKey: response.mainBtcPublicKey,
ordinalsAddress: response.ordinalsAddress,
masterPubKey: response.masterPubKey,
stxPublicKey: response.stxPublicKey,
Expand Down Expand Up @@ -123,10 +125,12 @@ export async function createWalletAccount(
stxAddress,
btcAddress,
ordinalsAddress,
mainBtcAddress,
masterPubKey,
stxPublicKey,
btcPublicKey,
ordinalsPublicKey,
mainBtcPublicKey,
} = await walletFromSeedPhrase({
mnemonic: seedPhrase,
index: BigInt(accountIndex),
Expand All @@ -139,6 +143,8 @@ export async function createWalletAccount(
id: accountIndex,
stxAddress,
btcAddress,
mainBtcAddress,
mainBtcPublicKey,
ordinalsAddress,
masterPubKey,
stxPublicKey,
Expand Down
13 changes: 12 additions & 1 deletion api/esplora/esploraAPiProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
BLOCKCYPHER_BASE_URI_MAINNET,
BLOCKCYPHER_BASE_URI_TESTNET,
BTC_BASE_URI_MAINNET,
BTC_BASE_URI_REGTEST,
BTC_BASE_URI_TESTNET,
} from '../../constant';
import {
Expand All @@ -29,7 +30,11 @@ export default class BitcoinEsploraApiProvider extends ApiInstance implements Bi
constructor(options: EsploraApiProviderOptions) {
const { url, network } = options;
super({
baseURL: url || network == 'Mainnet' ? BTC_BASE_URI_MAINNET : BTC_BASE_URI_TESTNET,
baseURL: url || network === 'Mainnet'
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here a sequence of ternaries seems a bit too confusing to read and understand. I would recommend just doing a switch, which will be more clear.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I see you did that in wallet/index.ts too, so it's probably more consistent too.

? BTC_BASE_URI_MAINNET
: network === 'Testnet'
? BTC_BASE_URI_TESTNET
: BTC_BASE_URI_REGTEST
});
this._network = network;

Expand Down Expand Up @@ -159,6 +164,12 @@ export default class BitcoinEsploraApiProvider extends ApiInstance implements Bi
};
}

async getRawTransaction(txHash: string): Promise<string> {
const data: string = await this.httpGet(`/tx/${txHash}/hex`);
return data;

}

async getRecommendedFees(): Promise<esplora.RecommendedFeeResponse> {
const data: esplora.RecommendedFeeResponse = await this.httpGet('/v1/fees/recommended');
return data;
Expand Down
8 changes: 6 additions & 2 deletions connect/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { createSha2Hash } from '@stacks/encryption';
import { ChainID } from '@stacks/transactions';
import { makeAuthResponse } from '@stacks/wallet-sdk';
import { GAIA_HUB_URL } from '../constant';
import { deriveStxAddressChain } from '../wallet/index';
import * as bip39 from 'bip39';
import { bip32 } from 'bitcoinjs-lib';
import { hashMessage } from '@stacks/encryption';
import { deriveStxAddressChain } from '../wallet/utils/stx';
import { GAIA_HUB_URL } from '../constant';


export async function createAuthResponse(
seedPhrase: string,
Expand Down Expand Up @@ -50,3 +52,5 @@ export async function createAuthResponse(

return;
}

export { hashMessage };
4 changes: 3 additions & 1 deletion constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const BTC_PATH = `m/49'/0'/0'/0/0`;

export const BTC_WRAPPED_SEGWIT_PATH_PURPOSE = `m/49'/`;

export const BTC_SEGWIT_PATH_PURPOSE = `m/84'/`;
export const BTC_SEGWIT_PATH_PURPOSE = `m/84'/0'`;

export const BTC_TAPROOT_PATH_PURPOSE = `m/86'/`;

Expand All @@ -26,6 +26,8 @@ export const BTC_BASE_URI_MAINNET = 'https://mempool.space/api';

export const BTC_BASE_URI_TESTNET = 'https://mempool.space/testnet/api';

export const BTC_BASE_URI_REGTEST = 'https://dev-oracle.dlc.link/electrs';

export const BLOCKCYPHER_BASE_URI_MAINNET = 'https://api.blockcypher.com/v1/btc/main';

export const BLOCKCYPHER_BASE_URI_TESTNET = 'https://api.blockcypher.com/v1/btc/test3';
Expand Down
10 changes: 9 additions & 1 deletion tests/btc/psbt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@ describe('Bitcoin PSBT tests', () => {

const nativeSegwitAddress2 = 'bc1q8agphg8kkn8ndvd5am8f44n3uzedcuaz437qdu';
const taprootAddress2 = 'bc1pzsm9pu47e7npkvxh9dcd0dc2qwqshxt2a9tt7aq3xe9krpl8e82sx6phdj';


const wrappedSegwitAddress3 = '3Gve89xYfW9RZRgRdN7hzCjXAHMDc7QRDf';
const taprootAddress3 = 'bc1pyzfhlkq29sylwlv72ve52w8mn7hclefzhyay3dxh32r0322yx6uqajvr3y';


const accounts = [
{
id: 0,
stxAddress: 'STXADDRESS1',
btcAddress: wrappedSegwitAddress1,
ordinalsAddress: taprootAddress1,
mainBtcAddress: '',
mainBtcPublicKey: '',
masterPubKey: '12345',
stxPublicKey: '123',
btcPublicKey: '123',
Expand All @@ -38,6 +42,8 @@ describe('Bitcoin PSBT tests', () => {
stxAddress: 'STXADDRESS2',
btcAddress: nativeSegwitAddress2,
ordinalsAddress: taprootAddress2,
mainBtcAddress: '',
mainBtcPublicKey: '',
masterPubKey: '12345',
stxPublicKey: '123',
btcPublicKey: '123',
Expand All @@ -48,6 +54,8 @@ describe('Bitcoin PSBT tests', () => {
stxAddress: 'STXADDRESS3',
btcAddress: wrappedSegwitAddress3,
ordinalsAddress: taprootAddress3,
mainBtcAddress: '',
mainBtcPublicKey: '',
masterPubKey: '12345',
stxPublicKey: '123',
btcPublicKey: '123',
Expand Down Expand Up @@ -77,7 +85,7 @@ describe('Bitcoin PSBT tests', () => {
'Mainnet'
);

expect(nativeSegwitPath).eq(`m/84'/0'/0'/0/1`);
expect(nativeSegwitPath).eq(`m/84'/0'/1'/0/0`);

const taprootPath = getSigningDerivationPath(
accounts,
Expand Down
2 changes: 1 addition & 1 deletion tests/btc/transactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
getBtcFees,
getBtcFeesForOrdinalSend,
} from '../../transactions/btc';
import { getBtcPrivateKey } from '../../wallet';
import { getBtcPrivateKey } from '../../wallet/utils/btc';
import { testSeed } from '../mocks/restore.mock';
import { UTXO } from '../../types';
import BigNumber from 'bignumber.js';
Expand Down
36 changes: 32 additions & 4 deletions tests/mocks/restore.mock.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Account } from "../../types";
import { Account } from '../../types';

export const testSeed = 'force kite borrow once shine pluck couch swift crystal swamp crumble essay';
export const testSeed =
'force kite borrow once shine pluck couch swift crystal swamp crumble essay';


export const walletAccounts: Account[] = [
{
id: 0,
Expand All @@ -10,6 +12,8 @@ export const walletAccounts: Account[] = [
btcPublicKey: '032215d812282c0792c8535c3702cca994f5e3da9cd8502c3e190d422f0066fdff',
ordinalsAddress: 'bc1pr09enf3yc43cz8qh7xwaasuv3xzlgfttdr3wn0q2dy9frkhrpdtsk05jqq',
ordinalsPublicKey: '5b21869d6643175e0530aeec51d265290d036384990ee60bf089b23ff6b9a367',
mainBtcAddress: 'bc1qf8njhm2nj48x9kltxvmc7vyl9cq7raukwg6mjk',
mainBtcPublicKey: '023537a32d5ab338a6ba52f13708ea45c1e3cb33c26aff3fa182d9c66fd4b636ff',
stxAddress: 'SP147ST7ESA3RES888QQMV6AK7GZK93ZR74A0GM7V',
stxPublicKey: '025df9b0ea2c81e4f8360bf9a16638ed3678bc84dbdc04124f5db86996999aa9a8',
},
Expand All @@ -18,11 +22,35 @@ export const walletAccounts: Account[] = [
masterPubKey: '024d30279814a0e609534af1d1969b7c24a6918029e1f9cb2134a427ebfb1f17c3',
btcAddress: '3EMRvkWMLaUfzHPA7Un5qfLZDvbXHn385u',
btcPublicKey: '022e633aba8838c039b2d2214f51ed284d3da7f585744f8975606376c23483d2c1',
mainBtcAddress: 'bc1qgxk5z97gempeav0xdrdcezhn9att7dev6gavyc',
mainBtcPublicKey: '03af366875dc848b7d8306b13c872f448791b7f7fbc8948e4452a07a74bff5f035',
ordinalsAddress: 'bc1pnc669rz0hyncjzxdgfeqm0dfhfr84ues4dwgq4lr47zpltzvekss4ptlxw',
ordinalsPublicKey: '380447c41546e736f3d4bf9dc075d2301f5252f33156e3564fd393eeffdaa347',
stxAddress: 'SP1BKESAFFV8ACW007HACXB93VHRFHP83BT24Z3NF',
stxPublicKey: '0302ec9c40f8d5daf319bf4b1556c7f51f1eb449dd96d05e7ed42a1056451dd656',
},
{
id: 2,
masterPubKey: '024d30279814a0e609534af1d1969b7c24a6918029e1f9cb2134a427ebfb1f17c3',
btcAddress: '3DUdrysnoh9CvMdtWhavTqRXhFvzg3aKNQ',
btcPublicKey: '036b7ca83c456a5b577d5631cd38c76c2d0540c25e6787bb4394001aebaea42d20',
mainBtcAddress: 'bc1q3xkz9q3fsxt6pxjxaq5w7yf6mhh4zxcu5d2fev',
mainBtcPublicKey: '03eb31409ecdcf37688b7d7ce1e915d8660208704695298b701a5652b05856d879',
ordinalsAddress: 'bc1pgu2hx6vkp0yja2sdeugkzs3xlxdwnj0wrasqletv8v98cn0vntesa2h8zv',
ordinalsPublicKey: 'ee3ad253e6696962b43ca3dd83a40dc3184e11ff0679f972a84704be36bc9225',
stxAddress: 'SP2BCTPVVHWN2VA8N85GRXJAPS10NR5YNFC6SY5SR',
stxPublicKey: '0268c588454446d214cbf7c7b0e970ba8cb3425f8976a045eed7f98112db7e1942',
},
{
btcAddress: '35xwHGuXcn4ufM2KDttL2w5PPsT9DRSoR6',
btcPublicKey: '03289a3a4d3b28565f5b5459d1570d8954bc08d09fb8d276154ff9cfeb0447bd10',
id: 3,
mainBtcAddress: 'bc1q85l49tvgpg09ztcn6dnp0ph4pxqy82xzhq48w2',
mainBtcPublicKey: '037465ac1d27643f071b88203497ba0d07bdb05e060923cd93a32d765b4f5f7158',
masterPubKey: '024d30279814a0e609534af1d1969b7c24a6918029e1f9cb2134a427ebfb1f17c3',
ordinalsAddress: 'bc1p6cz06dkrngdeuapgfuvahpnkvelmrcryk422kmd0y7zmuu2nechsyan7nk',
ordinalsPublicKey: '2cf69ea437dd236422e4490244c94e97664f4ad065dd280d83df5d5a22bef6b9',
stxAddress: 'SP1X4G7MZNTHGFF6DA58PN7EWQ72DGMF7834P6X8',
stxPublicKey: '0289e90678355f7b73e53a798fdb0a656d8faa2a186900f64cb8c06b7155f0e419',
},
];


2 changes: 1 addition & 1 deletion transactions/btc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import BigNumber from 'bignumber.js';
import { ErrorCodes, NetworkType, ResponseError, BtcFeeResponse, UTXO } from '../types';
import { fetchBtcFeeRate } from '../api/xverse';
import { getBtcPrivateKey, getBtcTaprootPrivateKey } from '../wallet';
import { getBtcPrivateKey, getBtcTaprootPrivateKey } from '../wallet/utils/btc';
import * as btc from '@scure/btc-signer';
import { hex } from '@scure/base';
import * as secp256k1 from '@noble/secp256k1';
Expand Down
9 changes: 8 additions & 1 deletion transactions/btcNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,19 @@ const bitcoinTestnet: BitcoinNetwork = {
wif: 0xef,
};

const bitcoinRegtest: BitcoinNetwork = {
bech32: 'bcrt',
pubKeyHash: 0x6f,
scriptHash: 0xc4,
wif: 0xef,
Comment on lines +25 to +28
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since these are used twice, consider defining them in a const object

};

export const bitcoinNetworks: Record<NetworkType, BitcoinNetwork> = {
Mainnet: bitcoinMainnet,
Testnet: bitcoinTestnet,
Regtest: bitcoinRegtest,
};

export const getBtcNetwork = (networkType: NetworkType) => {
return bitcoinNetworks[networkType];
};

4 changes: 1 addition & 3 deletions transactions/psbt.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { NetworkType, Account } from '../types';

import {
getBitcoinDerivationPath,
getTaprootDerivationPath,
getSegwitDerivationPath,
} from '../wallet';
} from '../wallet/utils/btc';
import * as btc from '@scure/btc-signer';
import { hex, base64 } from '@scure/base';
import { getAddressInfo } from 'bitcoin-address-validation';

import * as bip39 from 'bip39';
import { bip32 } from 'bitcoinjs-lib';
import * as secp256k1 from '@noble/secp256k1';
Expand Down
2 changes: 1 addition & 1 deletion transactions/stx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {
getNonce as fetchNewNonce,
} from '@stacks/transactions';
import { PostConditionsOptions, StxMempoolTransactionData } from 'types';
import { getStxAddressKeyChain } from '../wallet/index';
import { getStxAddressKeyChain } from '../wallet/utils/stx';
import { getNewNonce, makeFungiblePostCondition, makeNonFungiblePostCondition } from './helper';
import {
UnsignedContractCallTransaction,
Expand Down
2 changes: 2 additions & 0 deletions types/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export interface Account {
id: number;
stxAddress: string;
btcAddress: string;
mainBtcAddress: string;
mainBtcPublicKey: string;
ordinalsAddress: string;
masterPubKey: string;
stxPublicKey: string;
Expand Down
4 changes: 4 additions & 0 deletions types/api/blockcypher/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export interface BtcTransactionData extends TransactionData {
isOrdinal: boolean;
}

export interface BtcTransactionDataHexIncluded extends BtcTransactionData {
hex: string;
}

export interface Input {
addresses: string[];
output_index: number;
Expand Down
2 changes: 1 addition & 1 deletion types/network.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { StacksNetwork, StacksMainnet, StacksTestnet } from '@stacks/network';

export type NetworkType = 'Mainnet' | 'Testnet';
export type NetworkType = 'Mainnet' | 'Testnet' | 'Regtest';

export type SettingsNetwork = {
type: NetworkType;
Expand Down
2 changes: 2 additions & 0 deletions types/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export interface BaseWallet {
stxAddress: string;
btcAddress: string;
mainBtcAddress: string;
mainBtcPublicKey: string;
ordinalsAddress: string;
masterPubKey: string;
stxPublicKey: string;
Expand Down
44 changes: 43 additions & 1 deletion wallet/helper.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,50 @@
export function ecPairToHexString(secretKey: any) {
var ecPointHex = secretKey.privateKey.toString('hex');
const ecPointHex = secretKey.privateKey.toString('hex');
if (secretKey.compressed) {
return ecPointHex + '01';
} else {
return ecPointHex;
}
}

interface EncryptMnemonicArgs {
password: string;
seed: string;
passwordHashGenerator: (password: string) => Promise<{
salt: string;
hash: string;
}>;
mnemonicEncryptionHandler: (seed: string, key: string) => Promise<Buffer>;
}

interface DecryptMnemonicArgs {
password: string;
encryptedSeed: string;
passwordHashGenerator: (password: string) => Promise<{
salt: string;
hash: string;
}>;
mnemonicDecryptionHandler: (seed: Buffer | string, key: string) => Promise<string>;
}

export async function encryptMnemonicWithCallback(cb: EncryptMnemonicArgs) {
const { mnemonicEncryptionHandler, passwordHashGenerator, password, seed } = cb;
try {
const { hash } = await passwordHashGenerator(password);
const encryptedSeedBuffer = await mnemonicEncryptionHandler(seed, hash);
return encryptedSeedBuffer.toString('hex');
} catch (err) {
return Promise.reject(err);
}
}

export async function decryptMnemonicWithCallback(cb: DecryptMnemonicArgs) {
const { mnemonicDecryptionHandler, passwordHashGenerator, password, encryptedSeed } = cb;
try {
const { hash } = await passwordHashGenerator(password);
const seedPhrase = await mnemonicDecryptionHandler(encryptedSeed, hash);
return seedPhrase;
} catch (err) {
return Promise.reject(err);
}
}
Loading