Skip to content
Open
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
29 changes: 23 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ PORT=3002
HOST=0.0.0.0

# --- Database ---
# PostgreSQL connection string with credentials
# PostgreSQL connection string with credentials (required in production)
DATABASE_URL=postgresql://lens:lens@localhost:5432/lens
# Direct unpooled PostgreSQL connection string (used by Prisma migrations and CLI to bypass connection poolers)
DIRECT_DATABASE_URL=postgresql://lens:lens@localhost:5432/lens
Expand All @@ -31,7 +31,7 @@ PRICE_POINTS_DROP_EXPIRED=false
PRICE_POINTS_PRECREATE_DAYS=7

# --- Cache & Performance ---
# Redis connection URL for caching and queues
# Redis connection URL for caching and queues (required in production)
REDIS_URL=redis://localhost:6379
# How long to cache price responses in seconds (default: 10)
PRICE_CACHE_TTL=10
Expand Down Expand Up @@ -100,6 +100,10 @@ NETWORK_PASSPHRASE_TESTNET=Test SDF Network ; September 2015
SOROSWAP_FACTORY_ADDRESS_TESTNET=CDP3HMUH6SMS3S7NPGNDJLULCOXXEPSHY4JKUKMBNQMATHDHWXRRJTBY
# Soroswap has a testnet deployment; leave enabled. Set to "false" to disable.
SOROSWAP_ENABLED_TESTNET=true
# Optional per-network token-list override; otherwise SOROSWAP_TOKEN_LIST_URL is used.
SOROSWAP_TOKEN_LIST_URL_TESTNET=
# Optional per-network poll interval override in milliseconds.
SOROSWAP_POLL_INTERVAL_MS_TESTNET=
# Aquarius has no public testnet deployment today — disabled by default.
AQUARIUS_ENABLED_TESTNET=false
# DeFindex vault factory contract (56-char C... id) — from
Expand All @@ -116,6 +120,10 @@ PHOENIX_ENABLED_TESTNET=true
# Reflector oracle contract (56-char C... id) — see https://reflector.network. Empty = oracle disabled.
# A malformed id disables the oracle on this network and logs a warning naming this variable.
REFLECTOR_CONTRACT_ID_TESTNET=
# Set false to keep the oracle disabled even when a contract ID is configured.
REFLECTOR_ENABLED_TESTNET=true
# Optional per-network Aquarius endpoint override (falls back to AQUARIUS_API_URL).
AQUARIUS_API_URL_TESTNET=
# Blend lending pools (comma-separated 56-char C... ids) on testnet.
BLEND_POOLS_TESTNET=CCEBVDYM32YNYCVNRXQKDFFPISJJCV557CDZEIRBEE4NCV4KHPQ44HGF
# Blend backstop contract on testnet (56-char C... id).
Expand Down Expand Up @@ -152,6 +160,14 @@ NETWORK_PASSPHRASE_MAINNET=Public Global Stellar Network ; September 2015
SOROSWAP_FACTORY_ADDRESS_MAINNET=CA4HEQTL2WPEUYKYKCDOHCDNIV4QHNJ7EL4J4NQ6VADP7SYHVRYZ7AW2
SOROSWAP_ENABLED_MAINNET=true
AQUARIUS_ENABLED_MAINNET=true
# Optional per-network endpoint overrides (fall back to shared values).
AQUARIUS_API_URL_MAINNET=
SOROSWAP_TOKEN_LIST_URL_MAINNET=
SOROSWAP_POLL_INTERVAL_MS_MAINNET=
# Reflector oracle contract on mainnet (56-char C... id) — copy it from https://reflector.network.
# There is no built-in default: leave empty to keep the oracle disabled.
REFLECTOR_CONTRACT_ID_MAINNET=
REFLECTOR_ENABLED_MAINNET=true
# DeFindex vault factory contract on mainnet (56-char C... id) — from
# https://github.com/defindex-io/stellar-contracts (public/mainnet.contracts.json).
# A malformed id disables DeFindex on this network and logs a warning naming this variable.
Expand All @@ -168,7 +184,6 @@ PHOENIX_FACTORY_ADDRESS_MAINNET=CB4SVAWJA6TSRNOJZ7W2AWFW46D5VR4ZMFZKDIKXEINZCZEG
PHOENIX_ENABLED_MAINNET=true
# Reflector oracle contract on mainnet (56-char C... id) — copy it from https://reflector.network.
# There is no built-in default: leave empty to keep the oracle disabled.
REFLECTOR_CONTRACT_ID_MAINNET=
# Blend lending pools (comma-separated 56-char C... ids) on mainnet.
BLEND_POOLS_MAINNET=CAJJZSGMMM3PD7N33TAPHGBUGTB43OC73HVIK2L2G6BNGGGYOSSYBXBD,CCCCIQSDILITHMM7PBSLVDT5MISSY7R26MNZXCX4H7J5JQ5FPIYOGYFS,CDVQVKOY2YSXS2IC7KN6MNASSHPAO7UN2UR2ON4OI2SKMFJNVAMDX6DP,CBP7NO6F7FRDHSOFQBT2L2UWYIZ2PU76JKVRYAQTG3KZSQLYAOKIF2WB
# Blend backstop contract on mainnet (56-char C... id).
Expand Down Expand Up @@ -261,6 +276,8 @@ SDEX_PAGE_SIZE=200
AMM_PAGE_SIZE=200
# How often to poll Soroswap pool reserves in milliseconds (default: 60000 = 60s)
SOROSWAP_POLL_INTERVAL_MS=60000
# Legacy single-network facilitator fee setting (testnet fallback).
FACILITATOR_FEE_STROOPS=50000
# How often to poll Blend pool reserves in milliseconds (default: 60000 = 60s)
BLEND_POLL_INTERVAL_MS=60000
# Per-ingester cycle deadline in milliseconds (default: 60000 = 60s). A poll
Expand Down Expand Up @@ -305,9 +322,11 @@ WS_PING_INTERVAL_MS=30000
WS_MAX_MISSED_PINGS=2

# --- Auth & Security ---
# Secret key required for admin endpoints (e.g., adding/removing pairs)
# Secret key required for admin endpoints (e.g., adding/removing pairs); required in production
ADMIN_API_KEY=super-secret-admin-key

# Shared secret guarding the API-key admin endpoints (POST/DELETE /admin/keys); required in production
# and the `npm run key:issue` CLI. Send as the X-Admin-Token header.
# Shared secret guarding the API-key admin endpoints (POST/DELETE /admin/keys,
# GET /admin/usage) and the `npm run key:issue` CLI. Send as X-Admin-Token header
# or Authorization: Bearer <token>. When unset, empty, or a placeholder, the admin
Expand Down Expand Up @@ -497,7 +516,6 @@ RATE_PRUNE_BATCH_SIZE=1000
# Most a single payment may cost. Enforced as the x402 client's per-payment cap
# (spendControls.maxAmountPerPayment), so a call priced higher is refused before
# any money moves (default: $1.00).
MCP_MAX_PAYMENT_PRICE=$1.00
# Cumulative ceiling on what paid calls may cost in one UTC day. The per-call cap
# above only bounds one mistake; without this, an agent in a retry loop can pay
# that amount over and over. Once a further call's worst case no longer fits the
Expand Down Expand Up @@ -559,7 +577,6 @@ COINBASE_EXCHANGE_BASE_URL=
# Default: 30 days (defensible because downstream volume queries inspect up to
# 30-day windows, e.g. /volumes/:asset?window=30d, and it aligns with snapshot
# retention while preventing unbounded table growth).
PRICE_POINTS_RETENTION_DAYS=30

# Maximum rows removed by one database statement during a retention run.
# The job deletes in bounded batches using FOR UPDATE SKIP LOCKED and pauses
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/aggregateRefreshNetwork.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ const { mainnetPair, testnetPair } = vi.hoisted(() => ({
},
}))

vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
// activeNetwork and config.pairs are what the pre-fix worker read. They stay
// here so a regression fails on an assertion rather than at import time.
activeNetwork: 'testnet',
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/aquariusIngester.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const mocks = vi.hoisted(() => ({
},
}))

vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
config: mocks.config,
activeNetwork: 'testnet',
// startAquariusIngester / ingestAquariusPair resolve the per-network Aquarius
Expand Down
51 changes: 51 additions & 0 deletions src/__tests__/configEnvironment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { describe, expect, it, vi, afterEach } from 'vitest'
import { parseEnvironment } from '../config'

describe('environment validation', () => {
afterEach(() => {
vi.restoreAllMocks()
})

it('ignores a malformed numeric knob with a warning that names the variable and not its value', () => {
const env = parseEnvironment({ RATE_LIMIT_IP_MAX: 'lots' })
expect(env.RATE_LIMIT_IP_MAX).toBeUndefined()
})

it('ignores a malformed service URL so its default applies, instead of refusing to boot', () => {
const env = parseEnvironment({ REDIS_URL: 'cache-address' })
expect(env.REDIS_URL).toBeUndefined()
})

it('requires DATABASE_URL in production', () => {
expect(() => parseEnvironment({ NODE_ENV: 'production' }))
.toThrow('[config] Invalid environment: DATABASE_URL is required in production')
})

it('does not require optional services or admin secrets in production; their routes fail closed on their own', () => {
expect(() => parseEnvironment({
NODE_ENV: 'production',
DATABASE_URL: 'postgresql://lens:secret@db.example.com/lens',
})).not.toThrow()
})

it('accepts a complete production configuration and derives typed keys from the schema', () => {
const env = parseEnvironment({
NODE_ENV: 'production',
DATABASE_URL: 'postgresql://lens:secret@db.example.com/lens',
REDIS_URL: 'redis://cache.example.com:6379',
ADMIN_API_KEY: 'admin-key',
ADMIN_TOKEN: 'admin-token',
RATE_LIMIT_IP_MAX: '120',
REQUIRE_API_KEY: 'true',
})

expect(env.RATE_LIMIT_IP_MAX).toBe('120')
})

it('keeps well-formed values and drops only the malformed ones', () => {
const env = parseEnvironment({ PORT: '3002', HTTP_TIMEOUT_MS: 'soon', REQUIRE_API_KEY: 'false' })
expect(env.PORT).toBe('3002')
expect(env.HTTP_TIMEOUT_MS).toBeUndefined()
expect(env.REQUIRE_API_KEY).toBe('false')
})
})
3 changes: 2 additions & 1 deletion src/__tests__/correlation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const { mockQuery } = vi.hoisted(() => ({
vi.mock('../db', () => ({
pgPool: { query: mockQuery },
}))
vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
activeNetwork: 'testnet',
}))

Expand Down
1 change: 1 addition & 0 deletions src/__tests__/defindexIngester.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ vi.mock('../config', () => {
facilitator: { feeStroops: 50000 },
}
return {
getEnvironment: () => ({}), getEnvironmentValue: () => undefined,
activeNetwork: 'testnet',
getNetworkConfig: () => block,
config: { indexer: { pollIntervalMs: 5000 }, aquarius: { apiUrl: '' } },
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/enabledNetworks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { describe, it, expect, afterEach, vi } from 'vitest'

// activeNetwork is derived from STELLAR_NETWORK at config-module load; pin it so
// the fallback path is deterministic regardless of the ambient env.
vi.mock('../config', () => ({ activeNetwork: 'testnet' }))
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')), activeNetwork: 'testnet' }))

import { getEnabledNetworks } from '../network/enabledNetworks'

Expand Down
19 changes: 17 additions & 2 deletions src/__tests__/envDrift.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ export const UNDOCUMENTED_ENV_ALLOW_LIST: Record<string, string> = {
'Legacy unsuffixed fallback for testnet; FACILITATOR_FEE_STROOPS_TESTNET and FACILITATOR_FEE_STROOPS_MAINNET are documented in .env.example.',
API_KEY_LAST_USED_THROTTLE_SECONDS:
'Optional alias fallback; primary variable KEY_LAST_USED_THROTTLE_SECONDS is documented in .env.example.',
API_KEY_LAST_USED_THROTTLE_SECONDS:
'Optional alias fallback; primary variable KEY_LAST_USED_THROTTLE_SECONDS is documented in .env.example.',
}

/**
Expand Down Expand Up @@ -147,6 +145,10 @@ export function extractEnvReadsFromSource(sourceCode: string, fileName: string):
if (isProcessEnv(node.expression)) {
addRead(node.name.getText(sourceFile), node)
}
// Typed access through the shared validated config module.
if (node.expression.getText(sourceFile) === 'getEnvironment()') {
addRead(node.name.getText(sourceFile), node)
}
}

// 2. process.env['X'] or process.env[`X_${suffix}`]
Expand All @@ -165,6 +167,19 @@ export function extractEnvReadsFromSource(sourceCode: string, fileName: string):
}
}

// Keyed access through the shared validated config module.
if (ts.isCallExpression(node) && node.expression.getText(sourceFile) === 'getEnvironmentValue') {
const arg = node.arguments[0]
if (arg && ts.isStringLiteral(arg)) addRead(arg.text, node)
else if (arg && ts.isTemplateExpression(arg)) {
const head = arg.head.text
if (head.endsWith('_')) {
addRead(`${head}TESTNET`, node)
addRead(`${head}MAINNET`, node)
}
}
}

ts.forEachChild(node, visit)
}

Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/facilitator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ vi.mock('@x402/stellar', () => ({
createEd25519Signer: vi.fn(),
}))

vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
getNetworkConfig: vi.fn(() => ({
rpc: { url: 'http://localhost' },
facilitator: { secretKey: 'S_MOCK_SECRET', feeStroops: 50000 },
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/graphqlErrorMasking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ vi.mock('../redis', () => ({ getCachedPrice: vi.fn() }))
vi.mock('../db', () => ({ pgPool: { query: vi.fn() } }))
vi.mock('../aggregator/vwap', () => ({ getAggregatedPrice: vi.fn() }))
vi.mock('../aggregator/bestRoute', () => ({ getBestRoute: vi.fn() }))
vi.mock('../config', () => ({ config: { pairs: [] }, activeNetwork: 'testnet' }))
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')), config: { pairs: [] }, activeNetwork: 'testnet' }))

import { registerGraphQL } from '../api/graphql'
import { pgPool } from '../db'
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/graphqlOracle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ vi.mock('../redis', () => ({ getCachedPrice: vi.fn() }))
vi.mock('../db', () => ({ pgPool: { query: mockQuery } }))
vi.mock('../aggregator/vwap', () => ({ getAggregatedPrice: vi.fn() }))
vi.mock('../aggregator/bestRoute', () => ({ getBestRoute: vi.fn() }))
vi.mock('../config', () => ({ config: { pairs: [] }, activeNetwork: 'testnet' }))
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')), config: { pairs: [] }, activeNetwork: 'testnet' }))
vi.mock('../ingest/oracles/reflector', () => ({ reflectorOracleAdapter: mockAdapter }))

import { registerGraphQL } from '../api/graphql'
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/graphqlPairResolution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ vi.mock('../redis', () => ({ getCachedPrice: mocks.getCachedPrice }))
vi.mock('../db', () => ({ pgPool: { query: vi.fn() }, prisma: {} }))
vi.mock('../aggregator/vwap', () => ({ getAggregatedPrice: mocks.getAggregatedPrice }))
vi.mock('../aggregator/bestRoute', () => ({ getBestRoute: mocks.getBestRoute }))
vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
activeNetwork: 'testnet',
config: {
pairs: [
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/graphqlPairs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ vi.mock('../redis', () => ({ getCachedPrice: mocks.getCachedPrice }))
vi.mock('../db', () => ({ pgPool: { query: mocks.pgPoolQuery }, prisma: {} }))
vi.mock('../aggregator/vwap', () => ({ getAggregatedPrice: mocks.getAggregatedPrice }))
vi.mock('../aggregator/bestRoute', () => ({ getBestRoute: mocks.getBestRoute }))
vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
activeNetwork: 'mainnet',
config: {
pairs: mocks.pairs,
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/graphqlPriceHistory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ vi.mock('../db', () => ({
}))
vi.mock('../aggregator/vwap', () => ({ getAggregatedPrice: vi.fn() }))
vi.mock('../aggregator/bestRoute', () => ({ getBestRoute: vi.fn() }))
vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
config: { pairs: [], cache: { priceTtl: 60 } },
activeNetwork: 'testnet',
}))
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/graphqlQueryDepth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ vi.mock('../redis', () => ({ getCachedPrice: vi.fn() }))
vi.mock('../db', () => ({ pgPool: { query: vi.fn() } }))
vi.mock('../aggregator/vwap', () => ({ getAggregatedPrice: vi.fn() }))
vi.mock('../aggregator/bestRoute', () => ({ getBestRoute: vi.fn() }))
vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
activeNetwork: 'testnet',
config: {
pairs: [{
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/graphqlScreener.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ vi.mock('../db', () => ({ pgPool: { query: mockQuery }, prisma: {} }))
vi.mock('../redis', () => ({ getCachedPrice: vi.fn() }))
vi.mock('../aggregator/vwap', () => ({ getAggregatedPrice: vi.fn() }))
vi.mock('../aggregator/bestRoute', () => ({ getBestRoute: vi.fn() }))
vi.mock('../config', () => ({ config: { pairs: [] }, activeNetwork: 'testnet' }))
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')), config: { pairs: [] }, activeNetwork: 'testnet' }))

import { registerGraphQL } from '../api/graphql'
import { MARKET_CAP_UNSUPPORTED } from '../services/screener'
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/graphqlSubscription.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ vi.mock('../redis', () => ({ getCachedPrice: vi.fn() }))
vi.mock('../db', () => ({ pgPool: { query: vi.fn() } }))
vi.mock('../aggregator/vwap', () => ({ getAggregatedPrice: vi.fn() }))
vi.mock('../aggregator/bestRoute', () => ({ getBestRoute: vi.fn() }))
vi.mock('../config', () => ({ config: { pairs: [] } }))
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')), config: { pairs: [] } }))

import { registerGraphQL } from '../api/graphql'
import { publishPriceUpdate, priceEmitter } from '../events'
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/oracle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import Fastify from 'fastify'
const { mockQuery } = vi.hoisted(() => ({ mockQuery: vi.fn() }))

vi.mock('../db', () => ({ pgPool: { query: mockQuery } }))
vi.mock('../config', () => ({ activeNetwork: 'testnet' }))
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')), activeNetwork: 'testnet' }))
vi.mock('../ingest/oracles/reflector', () => ({
reflectorOracleAdapter: {
name: 'reflector',
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/phoenixIngester.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ const {

const mocks = fixtures

vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
config: { indexer: { pollIntervalMs: 5_000 } },
activeNetwork: 'testnet',
getNetworkConfig: (network: string) => mocks.networks[network],
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/price.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ const { testnetPairs, mainnetPairs } = vi.hoisted(() => ({
],
}))

vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
config: {
pairs: testnetPairs,
cache: { priceTtl: 10 },
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/rates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import Fastify from 'fastify'
const { mockQuery } = vi.hoisted(() => ({ mockQuery: vi.fn() }))

vi.mock('../db', () => ({ pgPool: { query: mockQuery } }))
vi.mock('../config', () => ({ activeNetwork: 'testnet' }))
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')), activeNetwork: 'testnet' }))

import { registerRateRoutes } from '../routes/rates'

Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/schemaValidation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ const { schemaTestPairs } = vi.hoisted(() => ({
],
}))

vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
config: {
pairs: schemaTestPairs,
cache: { priceTtl: 10 },
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/sep40Encoding.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
import { describe, it, expect, vi } from 'vitest'
import { Asset, Networks, StrKey } from '@stellar/stellar-sdk'

vi.mock('../config', () => ({
vi.mock('../config', async () => ({
...(await vi.importActual<typeof import('../config')>('../config')),
activeNetwork: 'testnet',
getNetworkConfig: (network: string) => ({
network: {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/sep40Publisher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const { configMock } = vi.hoisted(() => {
}
})

vi.mock('../config', () => configMock)
vi.mock('../config', () => ({ ...configMock, getEnvironment: () => ({}), getEnvironmentValue: () => undefined }))
vi.mock('../db', () => ({
pgPool: { query: vi.fn().mockResolvedValue({ rows: [] }) },
prisma: { oraclePublication: { create: vi.fn().mockResolvedValue({}) } },
Expand Down
Loading
Loading