@@ -9,6 +9,7 @@ import * as nock from 'nock';
9
9
import { DbBlock } from '../../src/datastore/common' ;
10
10
import { PgWriteStore } from '../../src/datastore/pg-write-store' ;
11
11
import { migrate } from '../utils/test-helpers' ;
12
+ import { MockAgent , setGlobalDispatcher , getGlobalDispatcher } from 'undici' ;
12
13
13
14
describe ( 'v2-proxy tests' , ( ) => {
14
15
let db : PgWriteStore ;
@@ -27,6 +28,95 @@ describe('v2-proxy tests', () => {
27
28
await migrate ( 'down' ) ;
28
29
} ) ;
29
30
31
+ test ( 'tx fee estimation' , async ( ) => {
32
+ const primaryProxyEndpoint = 'proxy-stacks-node:12345' ;
33
+ const feeEstimationModifier = 0.5 ;
34
+ await useWithCleanup (
35
+ ( ) => {
36
+ const restoreEnvVars = withEnvVars (
37
+ [ 'STACKS_CORE_FEE_ESTIMATION_MODIFIER' , feeEstimationModifier . toString ( ) ] ,
38
+ [ 'STACKS_CORE_PROXY_HOST' , primaryProxyEndpoint . split ( ':' ) [ 0 ] ] ,
39
+ [ 'STACKS_CORE_PROXY_PORT' , primaryProxyEndpoint . split ( ':' ) [ 1 ] ]
40
+ ) ;
41
+ return [ , ( ) => restoreEnvVars ( ) ] as const ;
42
+ } ,
43
+ ( ) => {
44
+ const agent = new MockAgent ( ) ;
45
+ const originalAgent = getGlobalDispatcher ( ) ;
46
+ setGlobalDispatcher ( agent ) ;
47
+ return [ agent , ( ) => setGlobalDispatcher ( originalAgent ) ] as const ;
48
+ } ,
49
+ async ( ) => {
50
+ const apiServer = await startApiServer ( {
51
+ datastore : db ,
52
+ chainId : ChainID . Mainnet ,
53
+ } ) ;
54
+ return [ apiServer , apiServer . terminate ] as const ;
55
+ } ,
56
+ async ( _ , mockAgent , api ) => {
57
+ const primaryStubbedResponse = {
58
+ cost_scalar_change_by_byte : 0.00476837158203125 ,
59
+ estimated_cost : {
60
+ read_count : 19 ,
61
+ read_length : 4814 ,
62
+ runtime : 7175000 ,
63
+ write_count : 2 ,
64
+ write_length : 1020 ,
65
+ } ,
66
+ estimated_cost_scalar : 14 ,
67
+ estimations : [
68
+ {
69
+ fee : 400 ,
70
+ fee_rate : 1.2410714285714286 ,
71
+ } ,
72
+ {
73
+ fee : 800 ,
74
+ fee_rate : 8.958333333333332 ,
75
+ } ,
76
+ {
77
+ fee : 1000 ,
78
+ fee_rate : 10 ,
79
+ } ,
80
+ ] ,
81
+ } ;
82
+ const testRequest = {
83
+ estimated_len : 350 ,
84
+ transaction_payload :
85
+ '021af942874ce525e87f21bbe8c121b12fac831d02f4086765742d696e666f0b7570646174652d696e666f00000000' ,
86
+ } ;
87
+
88
+ mockAgent
89
+ . get ( `http://${ primaryProxyEndpoint } ` )
90
+ . intercept ( {
91
+ path : '/v2/fees/transaction' ,
92
+ method : 'POST' ,
93
+ } )
94
+ . reply ( 200 , JSON . stringify ( primaryStubbedResponse ) , {
95
+ headers : { 'Content-Type' : 'application/json' } ,
96
+ } ) ;
97
+
98
+ const postTxReq = await supertest ( api . server )
99
+ . post ( `/v2/fees/transaction` )
100
+ . set ( 'Content-Type' , 'application/json' )
101
+ . send ( JSON . stringify ( testRequest ) ) ;
102
+ expect ( postTxReq . status ) . toBe ( 200 ) ;
103
+ // Expected min fee is the byte size because MINIMUM_TX_FEE_RATE_PER_BYTE=1
104
+ const expectedMinFee = Math . max (
105
+ testRequest . estimated_len ?? 0 ,
106
+ testRequest . transaction_payload . length / 2
107
+ ) ;
108
+ const expectedResponse = {
109
+ ...primaryStubbedResponse ,
110
+ } ;
111
+ expectedResponse . estimations = expectedResponse . estimations . map ( est => ( {
112
+ ...est ,
113
+ fee : Math . max ( expectedMinFee , Math . round ( est . fee * feeEstimationModifier ) ) ,
114
+ } ) ) ;
115
+ expect ( postTxReq . body ) . toEqual ( expectedResponse ) ;
116
+ }
117
+ ) ;
118
+ } ) ;
119
+
30
120
test ( 'tx post multicast' , async ( ) => {
31
121
const primaryProxyEndpoint = 'proxy-stacks-node:12345' ;
32
122
const extraTxEndpoint = 'http://extra-tx-endpoint-a/test' ;
0 commit comments