@@ -1745,11 +1745,16 @@ app.get('/api/wallet', async (req, res) => {
17451745 // Read-only — go straight to the RPC query client so Keplr/Privy
17461746 // sessions (which have no signing client; getClient() throws
17471747 // 'client-signs') can still fetch their balance. Falls back to the
1748- // signing client if RPC is unavailable.
1749- const rpc = await getRpcClient ( ) ;
1750- if ( rpc ) return rpcQueryBalance ( rpc , getAddr ( ) , 'udvpn' ) ;
1751- const client = await getSigningClient ( ) ;
1752- return client . getBalance ( getAddr ( ) , 'udvpn' ) ;
1748+ // LCD if RPC is unavailable.
1749+ try {
1750+ const rpc = await getRpcClient ( ) ;
1751+ if ( rpc ) return await rpcQueryBalance ( rpc , getAddr ( ) , 'udvpn' ) ;
1752+ } catch ( e ) {
1753+ console . log ( `[RPC] Balance query failed: ${ e . message } — LCD fallback` ) ;
1754+ }
1755+ const data = await lcd ( `/cosmos/bank/v1beta1/balances/${ getAddr ( ) } ` ) ;
1756+ const bal = data . balances ?. find ( b => b . denom === 'udvpn' ) ;
1757+ return { denom : 'udvpn' , amount : bal ? bal . amount : '0' } ;
17531758 } ) ,
17541759 getDvpnPrice ( ) ,
17551760 cached ( `provider:${ getAddr ( ) } ` , 600_000 , async ( ) => {
@@ -1968,8 +1973,15 @@ app.get('/api/my-plans', async (req, res) => {
19681973
19691974 const [ bal , ...myPlanResults ] = await Promise . all ( [
19701975 cached ( `balance:${ getAddr ( ) } ` , 30_000 , async ( ) => {
1971- const client = await getSigningClient ( ) ;
1972- return client . getBalance ( getAddr ( ) , 'udvpn' ) ;
1976+ try {
1977+ const rpc = await getRpcClient ( ) ;
1978+ if ( rpc ) return await rpcQueryBalance ( rpc , getAddr ( ) , 'udvpn' ) ;
1979+ } catch ( e ) {
1980+ console . log ( `[RPC] Balance query failed: ${ e . message } — LCD fallback` ) ;
1981+ }
1982+ const data = await lcd ( `/cosmos/bank/v1beta1/balances/${ getAddr ( ) } ` ) ;
1983+ const bal = data . balances ?. find ( b => b . denom === 'udvpn' ) ;
1984+ return { denom : 'udvpn' , amount : bal ? bal . amount : '0' } ;
19731985 } ) ,
19741986 // Resolve to {ok, planId, stats?, err?} so we never silently drop a
19751987 // plan when stats fail. The UI gets a stub row with the planId so the
@@ -2065,7 +2077,6 @@ app.post('/api/plan/create', async (req, res) => {
20652077
20662078 const bytesStr = String ( BigInt ( gigabytes ) * 1000000000n ) ;
20672079
2068- await getSigningClient ( ) ;
20692080 const msg = {
20702081 typeUrl : C . MSG_CREATE_PLAN_TYPE ,
20712082 value : {
@@ -2148,7 +2159,6 @@ app.post('/api/plan/status', async (req, res) => {
21482159 const ownErr = await assertPlanOwnership ( planId ) ;
21492160 if ( ownErr ) return res . status ( ownErr . status ) . json ( { error : ownErr . error } ) ;
21502161
2151- await getSigningClient ( ) ;
21522162 const msg = {
21532163 typeUrl : C . MSG_UPDATE_PLAN_STATUS_TYPE ,
21542164 value : { from : getProvAddr ( ) , id : BigInt ( planId ) , status : parseInt ( status ) } ,
@@ -2205,7 +2215,6 @@ app.post('/api/plan/subscribe', async (req, res) => {
22052215 const { planId, denom, renewalPolicy } = req . body ;
22062216 if ( ! planId ) return res . status ( 400 ) . json ( { error : 'planId required' } ) ;
22072217
2208- await getSigningClient ( ) ;
22092218 const msg = {
22102219 typeUrl : C . MSG_START_SUBSCRIPTION_TYPE ,
22112220 value : {
@@ -2251,7 +2260,6 @@ app.post('/api/plan/start-session', async (req, res) => {
22512260 const { subscriptionId, nodeAddress } = req . body ;
22522261 if ( ! subscriptionId || ! nodeAddress ) return res . status ( 400 ) . json ( { error : 'subscriptionId and nodeAddress required' } ) ;
22532262
2254- await getSigningClient ( ) ;
22552263 const msg = {
22562264 typeUrl : C . MSG_SUB_START_SESSION_TYPE ,
22572265 value : {
@@ -2492,7 +2500,6 @@ app.post('/api/plan-manager/link', async (req, res) => {
24922500 const ownErr = await assertPlanOwnership ( planId ) ;
24932501 if ( ownErr ) return res . status ( ownErr . status ) . json ( { error : ownErr . error } ) ;
24942502
2495- await getSigningClient ( ) ;
24962503 const linkMsg = {
24972504 typeUrl : C . MSG_LINK_TYPE ,
24982505 value : { from : getProvAddr ( ) , id : BigInt ( planId ) , nodeAddress } ,
@@ -2569,7 +2576,6 @@ app.post('/api/plan-manager/batch-link', async (req, res) => {
25692576 const addrs = [ ...new Set ( nodeAddresses ) ] ;
25702577 console . log ( `\n[BATCH-LINK] ${ addrs . length } nodes → plan ${ planId } (lease: ${ hours } h)` ) ;
25712578
2572- await getSigningClient ( ) ;
25732579
25742580 const linkMsgs = addrs . map ( addr => ( {
25752581 typeUrl : C . MSG_LINK_TYPE ,
@@ -2650,7 +2656,6 @@ app.post('/api/plan-manager/unlink', async (req, res) => {
26502656 const ownErr = await assertPlanOwnership ( planId ) ;
26512657 if ( ownErr ) return res . status ( ownErr . status ) . json ( { error : ownErr . error } ) ;
26522658
2653- await getSigningClient ( ) ;
26542659 const msg = {
26552660 typeUrl : C . MSG_UNLINK_TYPE ,
26562661 value : { from : getProvAddr ( ) , id : BigInt ( planId ) , nodeAddress } ,
@@ -2698,7 +2703,6 @@ app.post('/api/plan-manager/batch-unlink', async (req, res) => {
26982703 const addrs = [ ...new Set ( nodeAddresses ) ] ;
26992704 console . log ( `\n[BATCH-UNLINK] ${ addrs . length } nodes from plan ${ planId } ` ) ;
27002705
2701- await getSigningClient ( ) ;
27022706 const msgs = addrs . map ( addr => ( {
27032707 typeUrl : C . MSG_UNLINK_TYPE ,
27042708 value : { from : getProvAddr ( ) , id : BigInt ( planId ) , nodeAddress : addr } ,
@@ -2755,7 +2759,6 @@ app.post('/api/lease/start', async (req, res) => {
27552759 const quoteValue = String ( nodePrice . quote_value ?? nodePrice . quoteValue ) ;
27562760 console . log ( `[LEASE] Node price: ${ nodePrice . denom } base=${ baseValue } quote=${ quoteValue } ` ) ;
27572761
2758- await getSigningClient ( ) ;
27592762 const msg = {
27602763 typeUrl : C . MSG_START_LEASE_TYPE ,
27612764 value : {
@@ -2805,7 +2808,6 @@ app.post('/api/lease/end', async (req, res) => {
28052808 const { leaseId } = req . body ;
28062809 if ( ! leaseId ) return res . status ( 400 ) . json ( { error : 'leaseId required' } ) ;
28072810
2808- await getSigningClient ( ) ;
28092811 const msg = {
28102812 typeUrl : C . MSG_END_LEASE_TYPE ,
28112813 value : { from : getProvAddr ( ) , id : BigInt ( leaseId ) } ,
@@ -2846,7 +2848,6 @@ app.post('/api/provider/register', async (req, res) => {
28462848 const { name, identity, website, description } = req . body ;
28472849 if ( ! name ) return res . status ( 400 ) . json ( { error : 'name is required' } ) ;
28482850
2849- await getSigningClient ( ) ;
28502851
28512852 let alreadyExists = false ;
28522853 // RPC-first: direct lookup by sentprov address — exact match, no substring heuristic.
@@ -2935,7 +2936,6 @@ app.post('/api/provider/status', async (req, res) => {
29352936 const { status } = req . body ;
29362937 if ( ! status ) return res . status ( 400 ) . json ( { error : 'status required (1=active, 2=inactive_pending, 3=inactive)' } ) ;
29372938
2938- await getSigningClient ( ) ;
29392939 const msg = {
29402940 typeUrl : C . MSG_UPDATE_PROVIDER_STATUS_TYPE ,
29412941 value : { from : getProvAddr ( ) , status : parseInt ( status ) } ,
0 commit comments