@@ -5,7 +5,6 @@ import { getConfig } from '../config/env.js';
55import { getIssuer } from '../config/assets.js' ;
66import logger , { withContext } from '../config/logger.js' ;
77import prisma from '../db/client.js' ;
8- import { getIssuer } from '../config/assets.js' ;
98import { callWithCircuitBreaker } from './circuitBreaker.js' ;
109import { getCachedBalance , invalidateBalanceCache } from '../cache/balanceCache.js' ;
1110import { recordHorizonCall } from '../monitoring/horizonAlerter.js' ;
@@ -214,12 +213,6 @@ export async function createAccount(correlationId = null) {
214213 withContext ( logger , { action : 'createAccount' , correlationId } ) . info ( 'stellar.createAccount' , {
215214 publicKey,
216215 } ) ;
217- const pair = StellarSDK . Keypair . random ( ) ;
218- const publicKey = pair . publicKey ( ) ;
219- logger . info ( 'stellar.createAccount' , { publicKey } ) ;
220- withContext ( logger , { action : 'createAccount' , correlationId } ) . info ( 'stellar.createAccount' , {
221- publicKey,
222- } ) ;
223216
224217 if ( isTestnet ( ) ) {
225218 const friendbotRes = await fetch ( `https://friendbot.stellar.org?addr=${ publicKey } ` ) ;
@@ -249,18 +242,6 @@ export async function createAccount(correlationId = null) {
249242 create : { publicKey } ,
250243 } )
251244 . catch ( ( err ) => logger . warn ( 'db.user.upsert.failed' , { error : err . message , correlationId } ) ) ;
252- await prisma . user . upsert ( {
253- where : { publicKey } ,
254- update : { } ,
255- create : { publicKey } ,
256- } ) . catch ( err => logger . warn ( 'db.user.upsert.failed' , { error : err . message } ) ) ;
257- await prisma . user
258- . upsert ( {
259- where : { publicKey } ,
260- update : { } ,
261- create : { publicKey } ,
262- } )
263- . catch ( ( err ) => logger . warn ( 'db.user.upsert.failed' , { error : err . message , correlationId } ) ) ;
264245
265246 return {
266247 publicKey,
@@ -269,19 +250,6 @@ export async function createAccount(correlationId = null) {
269250 } ) ;
270251}
271252
272- export async function getBalance ( publicKey ) {
273- logger . debug ( 'stellar.getBalance' , { publicKey } ) ;
274- const account = await getHorizonServer ( ) . loadAccount ( publicKey ) ;
275- const balances = account . balances . map ( b => ( {
276- asset : b . asset_type === 'native' ? 'XLM' : `${ b . asset_code } :${ b . asset_issuer } ` ,
277- balance : b . balance
278- } ) ) ;
279-
280- logger . info ( 'stellar.balanceFetched' , { publicKey, balances } ) ;
281- await eventMonitor . publishEvent ( publicKey , {
282- type : 'BalanceChecked' ,
283- data : { balances } ,
284- version : 1
285253/**
286254 * Fetch all asset balances for a Stellar account from Horizon.
287255 * @param {string } publicKey - Stellar public key of the account
@@ -335,7 +303,6 @@ export async function sendPayment(
335303 // engineers can filter the full lifecycle with a single query.
336304 const txCorrelationId = correlationId ?? randomUUID ( ) ;
337305
338- const { assetIssuer } = getConfig ( ) . stellar ;
339306 const sourceKeypair = StellarSDK . Keypair . fromSecret ( sourceSecret ) ;
340307 const sourcePublicKey = sourceKeypair . publicKey ( ) ;
341308 logger . info ( 'stellar.sendPayment.start' , {
@@ -348,29 +315,6 @@ export async function sendPayment(
348315 correlationId : txCorrelationId ,
349316 } ) ;
350317
351- const sourceAccount = await getHorizonServer ( ) . loadAccount ( sourcePublicKey ) ;
352-
353- if ( assetCode !== 'XLM' && ! assetIssuer ) {
354- throw new Error ( 'ASSET_ISSUER is required for non-XLM payments' ) ;
355- }
356-
357- const asset = assetCode === 'XLM'
358- ? StellarSDK . Asset . native ( )
359- : new StellarSDK . Asset ( assetCode , getIssuer ( assetCode ) ) ;
360-
361- const transaction = new StellarSDK . TransactionBuilder ( sourceAccount , {
362- fee : StellarSDK . BASE_FEE ,
363- networkPassphrase : isTestnet ( )
364- ? StellarSDK . Networks . TESTNET
365- : StellarSDK . Networks . PUBLIC
366- } )
367- . addOperation ( StellarSDK . Operation . payment ( {
368- destination,
369- asset,
370- amount : amount . toString ( )
371- } ) )
372- . setTimeout ( 30 )
373- . build ( ) ;
374318 // Sequence Numbers
375319 // loadAccount fetches the current on-chain sequence number for the source account.
376320 // Every Stellar transaction must include a sequence number exactly one greater than
@@ -454,7 +398,6 @@ export async function sendPayment(
454398
455399 let result ;
456400 try {
457- result = await getHorizonServer ( ) . submitTransaction ( transaction ) ;
458401 result = await withHorizonRetry ( ( ) => getHorizonServer ( ) . submitTransaction ( txToSubmit ) ) ;
459402 } catch ( err ) {
460403 logger . error ( 'stellar.sendPayment.failed' , {
@@ -497,24 +440,6 @@ export async function sendPayment(
497440 version : 1 ,
498441 } ) ;
499442
500- // Persist transaction — ensure both users exist first
501- await prisma . $transaction ( async ( tx ) => {
502- const [ sender , recipient ] = await Promise . all ( [
503- tx . user . upsert ( { where : { publicKey : sourcePublicKey } , update : { } , create : { publicKey : sourcePublicKey } } ) ,
504- tx . user . upsert ( { where : { publicKey : destination } , update : { } , create : { publicKey : destination } } ) ,
505- ] ) ;
506- await tx . transaction . create ( {
507- data : {
508- hash : result . hash ,
509- assetCode : assetCode || 'XLM' ,
510- amount,
511- ledger : result . ledger ?? null ,
512- successful : result . successful ,
513- senderId : sender . id ,
514- recipientId : recipient . id ,
515- } ,
516- } ) ;
517- } ) . catch ( err => logger . warn ( 'db.transaction.save.failed' , { error : err . message } ) ) ;
518443 await prisma
519444 . $transaction ( async ( tx ) => {
520445 const [ sender , recipient ] = await Promise . all ( [
@@ -632,7 +557,6 @@ export async function createTrustline(sourceSecret, assetCode) {
632557 return { hash : result . hash , assetCode, issuer } ;
633558}
634559
635- export async function getTransactions ( publicKey , { cursor, limit = 10 , type, dateFrom, dateTo } = { } ) {
636560/**
637561 * Remove an existing trustline from an account. The asset balance must be zero.
638562 * @param {string } sourceSecret - Secret key of the account removing the trustline
@@ -786,7 +710,7 @@ export async function getTransactions(
786710/**
787711 * Retrieve current network fee statistics from Horizon with an XLM/USD conversion via the SDEX.
788712 * @returns {Promise<{feeStroops: number, feeXLM: string, feeUsd: string|null, xlmUsd: string|null,
789- * traditionalFeeUsd: number, baseFeeStroops: number, baseFeeXLM: string, surgeMultiplier: string }>}
713+ * traditionalFeeUsd: number}>}
790714 * @throws {Error } If the Horizon feeStats call fails
791715 */
792716export async function getFeeStats ( ) {
@@ -806,28 +730,6 @@ export async function getFeeStats() {
806730 } catch ( _ ) {
807731 /* non-critical: XLM/USD price lookup failure */
808732 }
809- const stats = await getHorizonServer ( ) . feeStats ( ) ;
810- const stats = await withHorizonRetry ( ( ) => getHorizonServer ( ) . feeStats ( ) ) ;
811- const baseFeeStroops = parseInt ( stats . last_ledger_base_fee ?? StellarSDK . BASE_FEE ) ;
812- const feeStroops = parseInt ( stats . fee_charged ?. mode ?? stats . fee_charged ?. p50 ?? StellarSDK . BASE_FEE ) ;
813- const feeXLM = feeStroops / 1e7 ;
814- const baseFeeXLM = baseFeeStroops / 1e7 ;
815- const surgeMultiplier = baseFeeStroops > 0 ? feeStroops / baseFeeStroops : 1 ;
816-
817- // Fetch XLM/USD price via Stellar SDEX (XLM/USDC order book)
818- let xlmUsd = null ;
819- try {
820- const usdc = new StellarSDK . Asset ( 'USDC' , 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN' ) ;
821- const book = await getHorizonServer ( ) . orderbook ( StellarSDK . Asset . native ( ) , usdc ) . limit ( 1 ) . call ( ) ;
822- const usdc = new StellarSDK . Asset ( 'USDC' , getIssuer ( 'USDC' ) ) ;
823- const book = await withHorizonRetry ( ( ) =>
824- getHorizonServer ( ) . orderbook ( StellarSDK . Asset . native ( ) , usdc ) . limit ( 1 ) . call ( ) ,
825- ) ;
826- const ask = parseFloat ( book . asks ?. [ 0 ] ?. price ) ;
827- if ( ask > 0 ) xlmUsd = ask ;
828- } catch ( _ ) {
829- /* non-critical: XLM/USD price lookup failure */
830- }
831733
832734 const feeUsd = xlmUsd ? feeXLM * xlmUsd : null ;
833735
@@ -839,17 +741,6 @@ export async function getFeeStats() {
839741 traditionalFeeUsd : 25 ,
840742 } ;
841743 } ) ;
842- return {
843- feeStroops,
844- feeXLM : feeXLM . toFixed ( 7 ) ,
845- feeUsd : feeUsd ? feeUsd . toFixed ( 6 ) : null ,
846- xlmUsd : xlmUsd ? xlmUsd . toFixed ( 4 ) : null ,
847- // Traditional wire transfer benchmark for comparison
848- traditionalFeeUsd : 25 ,
849- baseFeeStroops,
850- baseFeeXLM : baseFeeXLM . toFixed ( 7 ) ,
851- surgeMultiplier : surgeMultiplier . toFixed ( 2 ) ,
852- } ;
853744}
854745
855746export async function getTransactionHistory ( publicKey , { limit = 10 , cursor } = { } ) {
@@ -881,9 +772,6 @@ export async function getTransactionHistory(publicKey, { limit = 10, cursor } =
881772export async function getExchangeRate ( from , to ) {
882773 if ( from === to ) return 1.0 ;
883774 try {
884- const fromAsset = from === 'XLM' ? StellarSDK . Asset . native ( ) : new StellarSDK . Asset ( from , getIssuer ( from ) ) ;
885- const toAsset = to === 'XLM' ? StellarSDK . Asset . native ( ) : new StellarSDK . Asset ( to , getIssuer ( to ) ) ;
886- const orderbook = await getHorizonServer ( ) . orderbook ( fromAsset , toAsset ) . call ( ) ;
887775 const fromAsset =
888776 from === 'XLM' ? StellarSDK . Asset . native ( ) : new StellarSDK . Asset ( from , getIssuer ( from ) ) ;
889777 const toAsset =
@@ -928,29 +816,6 @@ export async function getNetworkStatus() {
928816 } ;
929817 }
930818 } ) ;
931- const { horizonUrl } = getConfig ( ) . stellar ;
932- try {
933- const root = await withHorizonRetry ( ( ) => getHorizonServer ( ) . root ( ) ) ;
934- const status = {
935- network : isTestnet ( ) ? 'testnet' : 'mainnet' ,
936- horizonUrl,
937- online : true ,
938- horizonVersion : root . horizon_version ,
939- networkPassphrase : root . network_passphrase ,
940- currentProtocolVersion : root . current_protocol_version ,
941- latencyMs : getLastHorizonLatency ( ) ?. latencyMs ?? null ,
942- } ;
943- logger . debug ( 'stellar.networkStatus' , status ) ;
944- return status ;
945- } catch ( err ) {
946- logger . warn ( 'stellar.networkStatus.offline' , { error : err . message } ) ;
947- return {
948- network : isTestnet ( ) ? 'testnet' : 'mainnet' ,
949- horizonUrl,
950- online : false ,
951- latencyMs : null ,
952- } ;
953- }
954819}
955820
956821// Horizon latency monitor: pings the Horizon root endpoint on an interval
@@ -988,6 +853,8 @@ export function startHorizonLatencyMonitor(intervalMs = LATENCY_PING_INTERVAL_MS
988853export function stopHorizonLatencyMonitor ( ) {
989854 if ( latencyPingTimer ) clearInterval ( latencyPingTimer ) ;
990855 latencyPingTimer = null ;
856+ }
857+
991858/**
992859 * List all non-native trustlines held by an account.
993860 * @param {string } publicKey - Stellar public key of the account
@@ -1070,17 +937,6 @@ export async function mergeAccount(sourceSecret, destination) {
1070937 } ;
1071938}
1072939
1073- /**
1074- * Build an unsigned XDR transaction envelope for a payment without submitting it to the network.
1075- * Useful for multisig workflows and hardware wallet signing.
1076- * @param {string } sourceSecret - Secret key of the source account (for sequence number)
1077- * @param {string } destination - Stellar public key of the recipient
1078- * @param {string } amount - Amount in stroops
1079- * @param {string } assetCode - Asset code (default: 'XLM')
1080- * @param {string } memo - Optional memo
1081- * @param {string } memoType - Type of memo ('text', 'id', 'hash', 'return')
1082- * @returns {Promise<{xdr: string}> } Base64-encoded unsigned transaction envelope
1083- */
1084940/**
1085941 * Simulate an account merge operation to show expected outcomes
1086942 * @param {string } sourcePublicKey - Public key of source account
@@ -1109,6 +965,17 @@ export async function simulateMergeAccount(sourcePublicKey, destinationPublicKey
1109965 } ;
1110966}
1111967
968+ /**
969+ * Build an unsigned XDR transaction envelope for a payment without submitting it to the network.
970+ * Useful for multisig workflows and hardware wallet signing.
971+ * @param {string } sourceSecret - Secret key of the source account (for sequence number)
972+ * @param {string } destination - Stellar public key of the recipient
973+ * @param {string } amount - Amount in stroops
974+ * @param {string } assetCode - Asset code (default: 'XLM')
975+ * @param {string } memo - Optional memo
976+ * @param {string } memoType - Type of memo ('text', 'id', 'hash', 'return')
977+ * @returns {Promise<{xdr: string}> } Base64-encoded unsigned transaction envelope
978+ */
1112979export async function buildUnsignedXdr (
1113980 sourceSecret ,
1114981 destination ,
0 commit comments