Skip to content
Merged
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
1 change: 1 addition & 0 deletions modules/abstract-utxo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
},
"devDependencies": {
"@bitgo/sdk-test": "^9.1.76",
"@bitgo/statics": "^59.15.0",
"@bitgo/utxo-lib": "^11.24.4",
"mocha": "^10.2.0"
},
Expand Down
1 change: 1 addition & 0 deletions modules/abstract-utxo/src/impl/btc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export * from './tbtc';
export * from './tbtc4';
export * from './tbtcsig';
export * from './tbtcbgsig';
export * from './tbtcstx';
export * from './inscriptionBuilder';
21 changes: 21 additions & 0 deletions modules/abstract-utxo/src/impl/btc/tbtcstx.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { BitGoBase } from '@bitgo/sdk-core';

import { UtxoCoinName, WasmUtxoCoinName } from '../../names';

import { Tbtc } from './tbtc';

export class Tbtcstx extends Tbtc {
readonly name: UtxoCoinName = 'tbtcstx';

constructor(bitgo: BitGoBase) {
super(bitgo);
}

static createInstance(bitgo: BitGoBase): Tbtcstx {
return new Tbtcstx(bitgo);
}

override get wasmName(): WasmUtxoCoinName {
return 'tbtcreg';
}
}
7 changes: 6 additions & 1 deletion modules/abstract-utxo/src/names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const utxoCoinsTestnet = [
'tbtc4',
'tbtcsig',
'tbtcbgsig',
'tbtcstx',
'tbch',
'tbcha',
'tbsv',
Expand All @@ -20,7 +21,7 @@ export const utxoCoinsTestnet = [
] as const;

export type UtxoCoinNameMainnet = (typeof utxoCoinsMainnet)[number];
export type UtxoCoinNameTestnet = `t${UtxoCoinNameMainnet}` | 'tbtcsig' | 'tbtc4' | 'tbtcbgsig';
export type UtxoCoinNameTestnet = `t${UtxoCoinNameMainnet}` | 'tbtcsig' | 'tbtc4' | 'tbtcbgsig' | 'tbtcstx';
export type UtxoCoinName = UtxoCoinNameMainnet | UtxoCoinNameTestnet;

export function toWasmUtxoCoinName(coinName: UtxoCoinName | WasmUtxoCoinName): WasmUtxoCoinName {
Expand Down Expand Up @@ -50,6 +51,7 @@ export function getMainnetCoinName(coinName: UtxoCoinName): UtxoCoinNameMainnet
case 'tbtc4':
case 'tbtcsig':
case 'tbtcbgsig':
case 'tbtcstx':
return 'btc';
default:
return coinName.slice(1) as UtxoCoinNameMainnet;
Expand Down Expand Up @@ -93,6 +95,9 @@ export function getFullNameFromCoinName(coinName: UtxoCoinName): string {
case 'tbtcbgsig':
prefix = 'BitGo Signet ';
break;
case 'tbtcstx':
prefix = 'Stacks ';
break;
default:
prefix = isUtxoCoinNameTestnet(coinName) ? 'Testnet ' : '';
}
Expand Down
28 changes: 28 additions & 0 deletions modules/abstract-utxo/test/unit/tbtcstx.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import assert from 'assert';

import { Networks } from '@bitgo/statics';
import * as utxolib from '@bitgo/utxo-lib';

import { Tbtcstx } from '../../src';

import { defaultBitGo, getNetworkForCoinName } from './util';

describe('tbtcstx', function () {
const coin = Tbtcstx.createInstance(defaultBitGo);

it('uses the public coin name with the testnet utxolib network', function () {
assert.strictEqual(coin.getChain(), 'tbtcstx');
assert.strictEqual(coin.wasmName, 'tbtcreg');
assert.strictEqual(Networks.test.bitcoinStx.utxolibName, 'testnet');
assert.strictEqual(getNetworkForCoinName(coin.name), utxolib.networks.testnet);
});

it('encodes and decodes private-1 addresses through the tbtcreg codec', function () {
const script = Buffer.from(`0014${'11'.repeat(20)}`, 'hex');
const address = coin.addressCodec.encode(script);

assert.match(address, /^bcrt1q/);
assert.deepStrictEqual(Buffer.from(coin.addressCodec.decode(address)), script);
assert.strictEqual(coin.isValidAddress(address), true);
});
});
51 changes: 19 additions & 32 deletions modules/abstract-utxo/test/unit/util/utxoCoins.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as utxolib from '@bitgo/utxo-lib';
import { BitGoAPI } from '@bitgo/sdk-api';
import { TestBitGo } from '@bitgo/sdk-test';
import { coins, UtxoCoin } from '@bitgo/statics';

import {
AbstractUtxoCoin,
Expand Down Expand Up @@ -30,50 +31,36 @@ import type { UtxoCoinName } from '../../../src/names';

export const defaultBitGo = TestBitGo.decorate(BitGoAPI, { env: 'mock' });

/** Map coin names to utxolib network objects for test infrastructure */
const coinNameToNetwork: Record<string, utxolib.Network> = {
btc: utxolib.networks.bitcoin,
tbtc: utxolib.networks.testnet,
tbtcsig: utxolib.networks.bitcoinPublicSignet,
tbtc4: utxolib.networks.bitcoinTestnet4,
tbtcbgsig: utxolib.networks.bitcoinBitGoSignet,
bch: utxolib.networks.bitcoincash,
tbch: utxolib.networks.bitcoincashTestnet,
bcha: utxolib.networks.ecash,
tbcha: utxolib.networks.ecashTest,
bsv: utxolib.networks.bitcoinsv,
tbsv: utxolib.networks.bitcoinsvTestnet,
btg: utxolib.networks.bitcoingold,
dash: utxolib.networks.dash,
tdash: utxolib.networks.dashTest,
doge: utxolib.networks.dogecoin,
tdoge: utxolib.networks.dogecoinTest,
ltc: utxolib.networks.litecoin,
tltc: utxolib.networks.litecoinTest,
zec: utxolib.networks.zcash,
tzec: utxolib.networks.zcashTest,
};
function isUtxolibNetworkName(name: string): name is utxolib.NetworkName {
return Object.prototype.hasOwnProperty.call(utxolib.networks, name);
}

/**
* Get utxolib Network for a coin name. For test infrastructure only.
* Get the utxolib network for a coin name from the canonical statics definition.
*/
export function getNetworkForCoinName(coinName: string): utxolib.Network {
const network = coinNameToNetwork[coinName];
if (!network) {
const coin = coins.getOrUndefined(coinName);
if (!(coin instanceof UtxoCoin)) {
throw new Error(`Unknown coin name: ${coinName}`);
}
return network;

const networkName = coin.network.utxolibName;
if (!isUtxolibNetworkName(networkName)) {
throw new Error(`Unknown utxolib network ${networkName} for coin ${coinName}`);
}

return utxolib.networks[networkName];
}

/**
* Get coin name for a utxolib Network. For test infrastructure only.
* Get the canonical test coin for a utxolib network.
*/
export function getCoinNameForNetwork(network: utxolib.Network): UtxoCoinName {
for (const [name, n] of Object.entries(coinNameToNetwork)) {
if (n === network) {
return name as UtxoCoinName;
}
const coin = utxoCoins.find((coin) => getNetworkForCoinName(coin.name) === network);
if (coin) {
return coin.name;
}

throw new Error(`Unknown network: ${utxolib.getNetworkName(network)}`);
}

Expand Down
2 changes: 2 additions & 0 deletions modules/bitgo/src/v2/coinFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ import {
Tbtcsig,
Tbtc4,
Tbtcbgsig,
Tbtcstx,
Tcanton,
Tcelo,
Tcoredao,
Expand Down Expand Up @@ -338,6 +339,7 @@ export function registerCoinConstructors(coinFactory: CoinFactory, coinMap: Coin
coinFactory.register('tbtcsig', Tbtcsig.createInstance);
coinFactory.register('tbtc4', Tbtc4.createInstance);
coinFactory.register('tbtcbgsig', Tbtcbgsig.createInstance);
coinFactory.register('tbtcstx', Tbtcstx.createInstance);
coinFactory.register('tcanton', Tcanton.createInstance);
coinFactory.register('tcelo', Tcelo.createInstance);
coinFactory.register('tcoredao', Tcoredao.createInstance);
Expand Down
4 changes: 2 additions & 2 deletions modules/bitgo/src/v2/coins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Bera, Tbera, BeraToken } from '@bitgo/sdk-coin-bera';
import { Bld, Tbld } from '@bitgo/sdk-coin-bld';
import { Bsc, BscToken, Tbsc } from '@bitgo/sdk-coin-bsc';
import { Bsv, Tbsv } from '@bitgo/sdk-coin-bsv';
import { Btc, Tbtc, Tbtcsig, Tbtc4, Tbtcbgsig } from '@bitgo/sdk-coin-btc';
import { Btc, Tbtc, Tbtcsig, Tbtc4, Tbtcbgsig, Tbtcstx } from '@bitgo/sdk-coin-btc';
import { Btg } from '@bitgo/sdk-coin-btg';
import { Canton, Tcanton } from '@bitgo/sdk-coin-canton';
import { Celo, CeloToken, Tcelo } from '@bitgo/sdk-coin-celo';
Expand Down Expand Up @@ -95,7 +95,7 @@ export { Bch, Tbch };
export { Bera, Tbera, BeraToken };
export { Bsc, BscToken, Tbsc };
export { Bsv, Tbsv };
export { Btc, Tbtc, Tbtcsig, Tbtc4, Tbtcbgsig };
export { Btc, Tbtc, Tbtcsig, Tbtc4, Tbtcbgsig, Tbtcstx };
export { Btg };
export { Canton, Tcanton };
export { Celo, CeloToken, Tcelo };
Expand Down
4 changes: 3 additions & 1 deletion modules/sdk-coin-btc/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { BitGoBase } from '@bitgo/sdk-core';
import { Btc, Tbtc, Tbtc4, Tbtcsig, Tbtcbgsig } from '@bitgo/abstract-utxo';
import { Btc, Tbtc, Tbtc4, Tbtcsig, Tbtcbgsig, Tbtcstx } from '@bitgo/abstract-utxo';

export { Btc, VerifyRecoveryTransactionOptions, InscriptionBuilder } from '@bitgo/abstract-utxo';
export { Tbtc } from '@bitgo/abstract-utxo';
export { Tbtcsig } from '@bitgo/abstract-utxo';
export { Tbtc4 } from '@bitgo/abstract-utxo';
export { Tbtcbgsig } from '@bitgo/abstract-utxo';
export { Tbtcstx } from '@bitgo/abstract-utxo';

export const register = (sdk: BitGoBase): void => {
sdk.register('btc', Btc.createInstance);
sdk.register('tbtc', Tbtc.createInstance);
sdk.register('tbtcsig', Tbtcsig.createInstance);
sdk.register('tbtcbgsig', Tbtcbgsig.createInstance);
sdk.register('tbtc4', Tbtc4.createInstance);
sdk.register('tbtcstx', Tbtcstx.createInstance);
};
9 changes: 9 additions & 0 deletions modules/statics/src/networks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,14 @@ class BitcoinBitGoSignet extends Testnet implements UtxoNetwork {
explorerUrl = 'https://mempool.space/notanetwork/tx/';
}

class BitcoinStx extends Testnet implements UtxoNetwork {
name = 'BitcoinStx';
family = CoinFamily.BTC;
// Stacks regtest uses testnet transaction semantics in utxo-lib.
utxolibName = 'testnet';
explorerUrl = undefined;
}

class BitcoinCash extends Mainnet implements UtxoNetwork {
name = 'BitcoinCash';
family = CoinFamily.BCH;
Expand Down Expand Up @@ -3070,6 +3078,7 @@ export const Networks = {
bitcoinPublicSignet: Object.freeze(new BitcoinPublicSignet()),
bitcoinTestnet4: Object.freeze(new BitcoinTestnet4()),
bitcoinBitGoSignet: Object.freeze(new BitcoinBitGoSignet()),
bitcoinStx: Object.freeze(new BitcoinStx()),
bitcoinCash: Object.freeze(new BitcoinCashTestnet()),
bitcoinGold: Object.freeze(new BitcoinGoldTestnet()),
bitcoinSV: Object.freeze(new BitcoinSVTestnet()),
Expand Down
10 changes: 10 additions & 0 deletions modules/statics/src/utxo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,16 @@ export const utxoCoins: Readonly<BaseCoin>[] = [
BaseUnit.BTC,
BTC_FEATURES
),
utxo(
'f3e1c2d4-5b6a-47c8-9012-3456789abcde',
'tbtcstx',
// Stacks Bitcoin regtest, represented by Bitcoin testnet transaction semantics in utxo-lib.
'Stacks Bitcoin (Regtest)',
Networks.test.bitcoinStx,
UnderlyingAsset.BTC,
BaseUnit.BTC,
BTC_FEATURES
),
utxo(
'8feb110d-0d68-44ce-ae97-b8c30ec870a9',
'btg',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const expectedColdFeatures = {
'tbtcsig',
'tbtc4',
'tbtcbgsig',
'tbtcstx',
'tcelo',
'tcspr',
'tdash',
Expand Down