Skip to content
Draft
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
14 changes: 11 additions & 3 deletions packages/wallet/wallet-toolbox/src/Setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -197,7 +198,10 @@ DEV_KEYS = '{
privilegedKeyGetter?: () => Promise<PrivateKey>
}): Promise<Wallet> {
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)
Expand All @@ -224,8 +228,12 @@ DEV_KEYS = '{
static async createWalletClient (args: SetupWalletClientArgs): Promise<SetupWalletClient> {
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)
Expand Down
14 changes: 12 additions & 2 deletions packages/wallet/wallet-toolbox/src/SetupClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -92,7 +94,10 @@ export abstract class SetupClient {
privilegedKeyGetter?: () => Promise<PrivateKey>
}): Promise<Wallet> {
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)
Expand All @@ -119,7 +124,12 @@ export abstract class SetupClient {
static async createWalletClient (args: SetupClientWalletClientArgs): Promise<SetupWalletClient> {
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 (`<arcade-host>/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
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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
Expand All @@ -18,8 +19,18 @@

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
// (`<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`)

Check warning on line 31 in packages/wallet/wallet-toolbox/src/services/chaintracker/ChaintracksChainTracker.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Simplify this regular expression to reduce its runtime, as it has super-linear performance due to backtracking.

See more on https://sonarcloud.io/project/issues?id=bsv-blockchain_ts-stack&issues=AZ-LzvOMEZmc0RtKqFtV&open=AZ-LzvOMEZmc0RtKqFtV&pullRequest=306
}
this.chaintracks = chaintracks
this.cache = {}
this.options = options || {}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Loading
Loading