diff --git a/packages/wallet/wallet-toolbox/src/Setup.ts b/packages/wallet/wallet-toolbox/src/Setup.ts index 5e31b487c..f858d5635 100644 --- a/packages/wallet/wallet-toolbox/src/Setup.ts +++ b/packages/wallet/wallet-toolbox/src/Setup.ts @@ -20,6 +20,7 @@ import { fundWalletFromP2PKHOutpoints as _fundWalletFromP2PKHOutpoints } from '. import { Chain } from './sdk/types' import { randomBytesHex, verifyTruthy } from './utility/utilityHelpers' import { WERR_INVALID_OPERATION } from './sdk/WERR_errors' +import { defaultStorageUrl } from './services/createDefaultWalletServicesOptions' import { WalletStorageManager } from './storage/WalletStorageManager' import { Services } from './services/Services' import { Monitor } from './monitor/Monitor' @@ -197,7 +198,10 @@ DEV_KEYS = '{ privilegedKeyGetter?: () => Promise }): Promise { const chain = args.chain - const endpointUrl = args.storageUrl || `https://${args.chain !== 'main' ? 'staging-' : ''}storage.babbage.systems` + const endpointUrl = args.storageUrl || defaultStorageUrl(chain) + if (endpointUrl == null) { + throw new WERR_INVALID_OPERATION(`chain '${chain}' has no default wallet-storage URL; provide storageUrl explicitly`) + } const rootKey = PrivateKey.fromHex(args.rootKeyHex) const keyDeriver = new CachedKeyDeriver(rootKey) const storage = new WalletStorageManager(keyDeriver.identityKey) @@ -224,8 +228,12 @@ DEV_KEYS = '{ static async createWalletClient (args: SetupWalletClientArgs): Promise { const wo = await Setup.createWallet(args) - const endpointUrl = - args.endpointUrl || `https://${args.env.chain !== 'main' ? 'staging-' : ''}storage.babbage.systems` + const endpointUrl = args.endpointUrl || defaultStorageUrl(args.env.chain) + if (endpointUrl == null) { + throw new WERR_INVALID_OPERATION( + `chain '${args.env.chain}' has no default wallet-storage URL; provide endpointUrl explicitly` + ) + } const client = new StorageClient(wo.wallet, endpointUrl) await wo.storage.addWalletStorageProvider(client) diff --git a/packages/wallet/wallet-toolbox/src/SetupClient.ts b/packages/wallet/wallet-toolbox/src/SetupClient.ts index f9d24e61a..333063c6b 100644 --- a/packages/wallet/wallet-toolbox/src/SetupClient.ts +++ b/packages/wallet/wallet-toolbox/src/SetupClient.ts @@ -23,6 +23,8 @@ import { Monitor } from './monitor/Monitor' import { PrivilegedKeyManager } from './sdk/PrivilegedKeyManager' import { Wallet } from './Wallet' import { Chain } from './sdk/types' +import { WERR_INVALID_OPERATION } from './sdk/WERR_errors' +import { defaultStorageUrl } from './services/createDefaultWalletServicesOptions' import { randomBytesHex } from './utility/utilityHelpers' import { StorageClient } from './storage/remoting/StorageClient' @@ -92,7 +94,10 @@ export abstract class SetupClient { privilegedKeyGetter?: () => Promise }): Promise { const chain = args.chain - const endpointUrl = args.storageUrl || `https://${args.chain !== 'main' ? 'staging-' : ''}storage.babbage.systems` + const endpointUrl = args.storageUrl || defaultStorageUrl(chain) + if (endpointUrl == null) { + throw new WERR_INVALID_OPERATION(`chain '${chain}' has no default wallet-storage URL; provide storageUrl explicitly`) + } const rootKey = PrivateKey.fromHex(args.rootKeyHex) const keyDeriver = new CachedKeyDeriver(rootKey) const storage = new WalletStorageManager(keyDeriver.identityKey) @@ -119,7 +124,12 @@ export abstract class SetupClient { static async createWalletClient (args: SetupClientWalletClientArgs): Promise { const wo = await SetupClient.createWallet(args) - const endpointUrl = args.endpointUrl || `https://${args.chain !== 'main' ? 'staging-' : ''}storage.babbage.systems` + const endpointUrl = args.endpointUrl || defaultStorageUrl(args.chain) + if (endpointUrl == null) { + throw new WERR_INVALID_OPERATION( + `chain '${args.chain}' has no default wallet-storage URL; provide endpointUrl explicitly` + ) + } const client = new StorageClient(wo.wallet, endpointUrl) await wo.storage.addWalletStorageProvider(client) diff --git a/packages/wallet/wallet-toolbox/src/sdk/WalletServices.interfaces.ts b/packages/wallet/wallet-toolbox/src/sdk/WalletServices.interfaces.ts index b91beac15..d96fa496e 100644 --- a/packages/wallet/wallet-toolbox/src/sdk/WalletServices.interfaces.ts +++ b/packages/wallet/wallet-toolbox/src/sdk/WalletServices.interfaces.ts @@ -276,18 +276,18 @@ export interface WalletServicesOptions { */ exchangeratesapiKey?: string /** - * Due to the default use of a free exchangeratesapiKey with low usage limits, - * the `ChaintracksService` can act as a request rate multiplier. + * Optional ChainTracks endpoint used to source fiat exchange rates. * - * By default the following endpoint is used: - * `https://mainnet-chaintracks.babbage.systems/getFiatExchangeRates` + * There is no default: fiat rates via ChainTracks are opt-in. Supply this URL (or an + * `exchangeratesapiKey`) to enable fiat exchange rate lookups. */ chaintracksFiatExchangeRatesUrl?: string /** * Optional Chaintracks client API instance. - * Default is a new instance of ChaintracksServiceClient configured to use: - * mainnet: `https://mainnet-chaintracks.babbage.systems` - * testnet: `https://testnet-chaintracks.babbage.systems` + * Default is a new instance of ChaintracksServiceClient pointed at the per-chain Arcade + * ChainTracks endpoint (`/chaintracks/v1`), e.g. + * mainnet: `https://arcade-v2-us-1.bsvblockchain.tech/chaintracks/v1` + * testnet: `https://arcade-v2-testnet-us-1.bsvblockchain.tech/chaintracks/v1` */ chaintracks?: ChaintracksClientApi /** diff --git a/packages/wallet/wallet-toolbox/src/services/__tests/Services.arcade.test.ts b/packages/wallet/wallet-toolbox/src/services/__tests/Services.arcade.test.ts index 26263e61a..43efe3929 100644 --- a/packages/wallet/wallet-toolbox/src/services/__tests/Services.arcade.test.ts +++ b/packages/wallet/wallet-toolbox/src/services/__tests/Services.arcade.test.ts @@ -10,10 +10,10 @@ import { arcadeDefaultUrl, createDefaultWalletServicesOptions } from '../createD const ARCADE_URL = 'https://arcade-v2-ttn-us-1.bsvblockchain.tech' describe('Services Arcade wiring', () => { - test('arcadeDefaultUrl maps known chains and omits testnet', () => { + test('arcadeDefaultUrl maps known chains', () => { expect(arcadeDefaultUrl('main')).toBe('https://arcade-v2-us-1.bsvblockchain.tech') expect(arcadeDefaultUrl('ttn')).toBe('https://arcade-v2-ttn-us-1.bsvblockchain.tech') - expect(arcadeDefaultUrl('test')).toBeUndefined() + expect(arcadeDefaultUrl('test')).toBe('https://arcade-v2-testnet-us-1.bsvblockchain.tech') }) test('arcadeDefaultUrl for tstn is driven by TSTN_ARCADE_URL', () => { diff --git a/packages/wallet/wallet-toolbox/src/services/__tests/getFiatExchangeRate.test.ts b/packages/wallet/wallet-toolbox/src/services/__tests/getFiatExchangeRate.test.ts index 98b42ae40..ec1d04778 100644 --- a/packages/wallet/wallet-toolbox/src/services/__tests/getFiatExchangeRate.test.ts +++ b/packages/wallet/wallet-toolbox/src/services/__tests/getFiatExchangeRate.test.ts @@ -21,7 +21,7 @@ const realFetch = global.fetch beforeAll(() => { global.fetch = jest.fn(async (input: any, init?: any) => { const url = typeof input === 'string' ? input : input?.url ?? '' - if (url.includes('chaintracks.babbage.systems/getFiatExchangeRates')) { + if (url.includes('/getFiatExchangeRates')) { return { ok: true, status: 200, json: async () => CHAINTRACKS_FIAT_RATES_PAYLOAD } as any } return realFetch(input, init) @@ -140,6 +140,8 @@ describe('getFiatExchangeRate service tests', () => { test('5 chaintracks works against the real service without an exchangeratesapi key', async () => { const options = Services.createDefaultOptions('main') + // No fiat-rates endpoint is configured by default; supply one to exercise the path. + options.chaintracksFiatExchangeRatesUrl = 'https://chaintracks.example.test/getFiatExchangeRates' options.fiatExchangeRates = { timestamp: new Date('2020-01-01T00:00:00.000Z'), base: 'USD', diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/ChaintracksChainTracker.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/ChaintracksChainTracker.ts index 1ea727549..ce47d7e9d 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/ChaintracksChainTracker.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/ChaintracksChainTracker.ts @@ -5,6 +5,7 @@ import { WalletError } from '../../sdk/WalletError' import { wait } from '../../utility/utilityHelpers' import { BlockHeader } from '../../sdk/WalletServices.interfaces' import { ChaintracksClientApi } from './chaintracks/Api/ChaintracksClientApi' +import { arcadeDefaultUrl } from '../createDefaultWalletServicesOptions' export interface ChaintracksChainTrackerOptions { maxRetries?: number @@ -18,8 +19,18 @@ export class ChaintracksChainTracker implements ChainTracker { constructor (chain?: Chain, chaintracks?: ChaintracksClientApi, options?: ChaintracksChainTrackerOptions) { chain ||= 'main' - this.chaintracks = - chaintracks ?? new ChaintracksServiceClient(chain, `https://${chain}net-chaintracks.babbage.systems`) + if (chaintracks == null) { + // Derive the default ChainTracks endpoint from the per-chain Arcade host + // (`/chaintracks/v1`); no hardcoded babbage endpoint. + const arcadeHost = arcadeDefaultUrl(chain) + if (arcadeHost == null || arcadeHost === '') { + throw new Error( + `ChaintracksChainTracker: no default ChainTracks endpoint for chain '${chain}'; provide a chaintracks client` + ) + } + chaintracks = new ChaintracksServiceClient(chain, `${arcadeHost.replace(/\/+$/, '')}/chaintracks/v1`) + } + this.chaintracks = chaintracks this.cache = {} this.options = options || {} } diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/__tests/ChaintracksChainTracker.test.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/__tests/ChaintracksChainTracker.test.ts index 817805c23..4132e8785 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/__tests/ChaintracksChainTracker.test.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/__tests/ChaintracksChainTracker.test.ts @@ -21,10 +21,10 @@ const realFetch = global.fetch beforeAll(() => { global.fetch = jest.fn(async (input: any, init?: any) => { const url = typeof input === 'string' ? input : input?.url ?? '' - if (url.includes('chaintracks.babbage.systems/getPresentHeight')) { + if (url.includes('/getPresentHeight')) { return jsonResponse({ status: 'success', value: 950000 }) } - if (url.includes('chaintracks.babbage.systems/findHeaderHexForHeight')) { + if (url.includes('/findHeaderHexForHeight')) { const height = Number(new URL(url).searchParams.get('height')) if (height === 877599) { return jsonResponse({ status: 'success', value: HEADER_877599 }) diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDNBabbage.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDNBabbage.ts index bb1e88cf2..ed57285e1 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDNBabbage.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/Ingest/BulkIngestorCDNBabbage.ts @@ -11,7 +11,7 @@ export class BulkIngestorCDNBabbage extends BulkIngestorCDN { */ static createBulkIngestorCDNBabbageOptions (chain: Chain, fetch: ChaintracksFetchApi): BulkIngestorCDNOptions { const options: BulkIngestorCDNOptions = { - ...BulkIngestorCDN.createBulkIngestorCDNOptions(chain, 'https://cdn.projectbabbage.com/blockheaders/', fetch) + ...BulkIngestorCDN.createBulkIngestorCDNOptions(chain, 'https://chaintracks-cdn-us-1.bsvb.tech/', fetch) } return options } diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.ts index 7350ccd4c..635c56cde 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.ts @@ -12,7 +12,7 @@ export function createDefaultIdbChaintracksOptions ( maxPerFile: number = 100000, maxRetained: number = 2, fetch?: ChaintracksFetchApi, - cdnUrl: string = 'https://cdn.projectbabbage.com/blockheaders/', + cdnUrl: string = 'https://chaintracks-cdn-us-1.bsvb.tech/', liveHeightThreshold: number = 2000, reorgHeightThreshold: number = 400, bulkMigrationChunkSize: number = 500, diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.ts index dbd4b9529..41dbbfc18 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.ts @@ -22,7 +22,7 @@ export function createDefaultKnexChaintracksOptions ( maxPerFile: number = 100000, maxRetained: number = 2, fetch?: ChaintracksFetchApi, - cdnUrl: string = 'https://cdn.projectbabbage.com/blockheaders/', + cdnUrl: string = 'https://chaintracks-cdn-us-1.bsvb.tech/', liveHeightThreshold: number = 2000, reorgHeightThreshold: number = 400, bulkMigrationChunkSize: number = 500, diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.ts index 9040476ed..79ecaac79 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.ts @@ -12,7 +12,7 @@ export function createDefaultNoDbChaintracksOptions ( maxPerFile: number = 100000, maxRetained: number = 2, fetch?: ChaintracksFetchApi, - cdnUrl: string = 'https://cdn.projectbabbage.com/blockheaders/', + cdnUrl: string = 'https://chaintracks-cdn-us-1.bsvb.tech/', liveHeightThreshold: number = 2000, reorgHeightThreshold: number = 400, bulkMigrationChunkSize: number = 500, diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createIdbChaintracks.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createIdbChaintracks.ts index 63063153e..21c8664ee 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createIdbChaintracks.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createIdbChaintracks.ts @@ -11,7 +11,7 @@ export async function createIdbChaintracks ( maxPerFile: number = 100000, maxRetained: number = 2, fetch?: ChaintracksFetchApi, - cdnUrl: string = 'https://cdn.projectbabbage.com/blockheaders/', + cdnUrl: string = 'https://chaintracks-cdn-us-1.bsvb.tech/', liveHeightThreshold: number = 2000, reorgHeightThreshold: number = 400, bulkMigrationChunkSize: number = 500, diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createKnexChaintracks.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createKnexChaintracks.ts index 45a047869..4093ac1b5 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createKnexChaintracks.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createKnexChaintracks.ts @@ -15,7 +15,7 @@ export async function createKnexChaintracks ( maxPerFile: number = 100000, maxRetained: number = 2, fetch?: ChaintracksFetchApi, - cdnUrl: string = 'https://cdn.projectbabbage.com/blockheaders/', + cdnUrl: string = 'https://chaintracks-cdn-us-1.bsvb.tech/', liveHeightThreshold: number = 2000, reorgHeightThreshold: number = 400, bulkMigrationChunkSize: number = 500, diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createNoDbChaintracks.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createNoDbChaintracks.ts index bcaea5132..0cc670a72 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createNoDbChaintracks.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/createNoDbChaintracks.ts @@ -11,7 +11,7 @@ export async function createNoDbChaintracks ( maxPerFile: number = 100000, maxRetained: number = 2, fetch?: ChaintracksFetchApi, - cdnUrl: string = 'https://cdn.projectbabbage.com/blockheaders/', + cdnUrl: string = 'https://chaintracks-cdn-us-1.bsvb.tech/', liveHeightThreshold: number = 2000, reorgHeightThreshold: number = 400, bulkMigrationChunkSize: number = 500, diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/BulkFileDataManager.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/BulkFileDataManager.ts index 916470730..593beb585 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/BulkFileDataManager.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/BulkFileDataManager.ts @@ -44,7 +44,7 @@ export class BulkFileDataManager { maxPerFile: 100000, maxRetained: 2, fetch: new ChaintracksFetch(), - fromKnownSourceUrl: 'https://cdn.projectbabbage.com/blockheaders' + fromKnownSourceUrl: 'https://chaintracks-cdn-us-1.bsvb.tech' } } diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/__tests/BulkFileDataManager.test.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/__tests/BulkFileDataManager.test.ts index 6742053ae..3a7c4f3f9 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/__tests/BulkFileDataManager.test.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/__tests/BulkFileDataManager.test.ts @@ -66,7 +66,7 @@ describe('BulkFileDataManager tests', () => { expect(manager.chain).toBe(chain) expect(manager.maxPerFile).toBe(100000) expect(manager.maxRetained).toBe(2) - expect(manager.fromKnownSourceUrl).toBe('https://cdn.projectbabbage.com/blockheaders') + expect(manager.fromKnownSourceUrl).toBe('https://chaintracks-cdn-us-1.bsvb.tech') const files = await manager.getBulkFiles() expect(files.length).toBeGreaterThan(7) const range = await manager.getHeightRange() diff --git a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.ts b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.ts index 4a3da1c66..14731f173 100644 --- a/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.ts +++ b/packages/wallet/wallet-toolbox/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.ts @@ -65,7 +65,7 @@ export function validBulkHeaderFilesByFileHash (): Record/chaintracks/v1`) for + // every public network; tstn resolves its private endpoint from the environment. let chaintracksUrl: string - if (chain === 'ttn') { - chaintracksUrl = 'https://arcade-v2-ttn-us-1.bsvblockchain.tech/chaintracks/v1' - } else if (chain === 'tstn') { + if (chain === 'tstn') { chaintracksUrl = tstnChaintracksUrl() } else { - chaintracksUrl = `https://${chain}net-chaintracks.babbage.systems` + const arcadeHost = arcadeDefaultUrl(chain) + if (arcadeHost == null || arcadeHost === '') { + throw new Error(`chain '${chain}' has no Arcade host to derive a ChainTracks URL from`) + } + chaintracksUrl = `${arcadeHost.replace(/\/+$/, '')}/chaintracks/v1` } - // The mainnet endpoint is always used since these are fiat exchange rates, - // independent of the chain being used. - const chaintracksFiatExchangeRatesUrl = 'https://mainnet-chaintracks.babbage.systems/getFiatExchangeRates' + // Fiat exchange rates have no supported default endpoint. Operators that need them must + // supply `chaintracksFiatExchangeRatesUrl` (or an `exchangeratesapiKey`) explicitly. + const chaintracksFiatExchangeRatesUrl: string | undefined = undefined chaintracks ||= new ChaintracksServiceClient(chain, chaintracksUrl) @@ -116,7 +119,8 @@ export function createDefaultWalletServicesOptions ( /** * Default Arcade (bsv-blockchain/arcade) endpoint per chain. - * Returns undefined when no public default is known for the chain (e.g. testnet not yet deployed). + * Returns undefined only when no default is known for the chain: `tstn` until + * `TSTN_ARCADE_URL` is supplied at runtime, and `mock`. */ export function arcadeDefaultUrl (chain: Chain): string | undefined { switch (chain) { @@ -128,8 +132,7 @@ export function arcadeDefaultUrl (chain: Chain): string | undefined { // Private per-deployment endpoint supplied via TSTN_ARCADE_URL (undefined when unset). return tstnArcadeUrl() case 'test': - // No public testnet Arcade endpoint deployed yet. - return undefined + return 'https://arcade-v2-testnet-us-1.bsvblockchain.tech' case 'mock': return undefined } @@ -154,3 +157,23 @@ export function arcDefaultUrl (chain: Chain): string { export function arcGorillaPoolUrl (chain: Chain): string | undefined { return chain === 'main' ? 'https://arc.gorillapool.io' : undefined } + +/** + * Default wallet-storage (`StorageClient`) endpoint per chain. + * Returns undefined for chains without a public default: `tstn` is private/per-deployment, + * and `mock`. Callers must then supply an explicit storage URL. + */ +export function defaultStorageUrl (chain: Chain): string | undefined { + switch (chain) { + case 'main': + return 'https://store-us-1.bsvb.tech' + case 'test': + return 'https://store-testnet-us-1.bsvb.tech' + case 'ttn': + return 'https://store-ttn-us-1.bsvb.tech' + case 'tstn': + return undefined + case 'mock': + return undefined + } +}