This repository has been archived by the owner on Oct 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(BUX-149): fee quotes implemented (#7)
* feat(BUX-149): fee quotes implemented * refactor: changing best quote to be parallel
- Loading branch information
1 parent
3be1b74
commit c15d749
Showing
18 changed files
with
770 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package broadcast | ||
|
||
import "time" | ||
|
||
const ( | ||
DefaultFastestQuoteTimeout = 10 * time.Second | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package broadcast | ||
|
||
type PolicyQuoteResponse struct { | ||
Miner string `json:"miner"` | ||
Policy PolicyResponse `json:"policy"` | ||
Timestamp string `json:"timestamp"` | ||
} | ||
|
||
type FeeQuote struct { | ||
Miner string `json:"miner"` | ||
MiningFee MiningFeeResponse `json:"miningFee"` | ||
Timestamp string `json:"timestamp"` | ||
} | ||
|
||
type PolicyResponse struct { | ||
MaxScriptSizePolicy int64 `json:"maxscriptsizepolicy"` | ||
MaxTxSigOpsCountPolicy int64 `json:"maxtxsigopscountspolicy"` | ||
MaxTxSizePolicy int64 `json:"maxtxsizepolicy"` | ||
MiningFee MiningFeeResponse `json:"miningFee"` | ||
} | ||
|
||
type MiningFeeResponse struct { | ||
Bytes int64 `json:"bytes"` | ||
Satoshis int64 `json:"satoshis"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package arc | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/bitcoin-sv/go-broadcast-client/broadcast" | ||
) | ||
|
||
func (a *ArcClient) GetBestQuote(ctx context.Context) (*broadcast.FeeQuote, error) { | ||
policyQuote, err := a.GetPolicyQuote(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
feeQuote := &broadcast.FeeQuote{ | ||
Miner: a.apiURL, | ||
MiningFee: policyQuote.Policy.MiningFee, | ||
Timestamp: policyQuote.Timestamp, | ||
} | ||
return feeQuote, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package arc | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"errors" | ||
"io" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/mock" | ||
|
||
"github.com/bitcoin-sv/go-broadcast-client/broadcast" | ||
) | ||
|
||
func TestBestQuote(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
httpResponse *http.Response | ||
httpError error | ||
expectedResult *broadcast.FeeQuote | ||
expectedError error | ||
}{ | ||
{ | ||
name: "successful request", | ||
httpResponse: &http.Response{ | ||
StatusCode: http.StatusOK, | ||
Body: io.NopCloser(bytes.NewBufferString(` | ||
{ | ||
"policy": { | ||
"maxscriptsizepolicy": 100000000, | ||
"maxtxsigopscountspolicy": 4294967295, | ||
"maxtxsizepolicy": 100000000, | ||
"miningFee": { | ||
"bytes": 1000, | ||
"satoshis": 1 | ||
} | ||
}, | ||
"timestamp": "2023-08-10T13:49:07.308687569Z" | ||
} | ||
`)), | ||
}, | ||
expectedResult: &broadcast.FeeQuote{ | ||
Miner: "http://example.com", | ||
MiningFee: broadcast.MiningFeeResponse{ | ||
Bytes: 1000, | ||
Satoshis: 1, | ||
}, | ||
Timestamp: "2023-08-10T13:49:07.308687569Z", | ||
}, | ||
}, | ||
{ | ||
name: "error in HTTP request", | ||
httpError: errors.New("some error"), | ||
expectedError: errors.New("some error"), | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
// given | ||
mockHttpClient := new(MockHttpClient) | ||
|
||
mockHttpClient.On("DoRequest", context.Background(), mock.Anything). | ||
Return(tc.httpResponse, tc.httpError).Once() | ||
|
||
client := &ArcClient{ | ||
HTTPClient: mockHttpClient, | ||
apiURL: "http://example.com", | ||
token: "someToken", | ||
} | ||
|
||
// when | ||
result, err := client.GetBestQuote(context.Background()) | ||
|
||
// then | ||
assert.Equal(t, tc.expectedResult, result) | ||
assert.Equal(t, tc.expectedError, err) | ||
|
||
// assert Expectations on the mock | ||
mockHttpClient.AssertExpectations(t) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package arc | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"github.com/bitcoin-sv/go-broadcast-client/broadcast" | ||
) | ||
|
||
func (a *ArcClient) GetFastestQuote( | ||
ctx context.Context, | ||
timeout time.Duration, | ||
) (*broadcast.FeeQuote, error) { | ||
if timeout.Seconds() == 0 { | ||
timeout = broadcast.DefaultFastestQuoteTimeout | ||
} | ||
|
||
ctxWithTimeout, cancel := context.WithTimeout(ctx, timeout) | ||
defer cancel() | ||
|
||
policyQuote, err := a.GetPolicyQuote(ctxWithTimeout) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
feeQuote := &broadcast.FeeQuote{ | ||
Miner: a.apiURL, | ||
MiningFee: policyQuote.Policy.MiningFee, | ||
Timestamp: policyQuote.Timestamp, | ||
} | ||
return feeQuote, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package arc | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"errors" | ||
"io" | ||
"net/http" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/mock" | ||
|
||
"github.com/bitcoin-sv/go-broadcast-client/broadcast" | ||
) | ||
|
||
func TestFastestQuote(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
httpResponse *http.Response | ||
httpError error | ||
expectedResult *broadcast.FeeQuote | ||
expectedError error | ||
}{ | ||
{ | ||
name: "successful request", | ||
httpResponse: &http.Response{ | ||
StatusCode: http.StatusOK, | ||
Body: io.NopCloser(bytes.NewBufferString(` | ||
{ | ||
"policy": { | ||
"maxscriptsizepolicy": 100000000, | ||
"maxtxsigopscountspolicy": 4294967295, | ||
"maxtxsizepolicy": 100000000, | ||
"miningFee": { | ||
"bytes": 1000, | ||
"satoshis": 1 | ||
} | ||
}, | ||
"timestamp": "2023-08-10T13:49:07.308687569Z" | ||
} | ||
`)), | ||
}, | ||
expectedResult: &broadcast.FeeQuote{ | ||
Miner: "http://example.com", | ||
MiningFee: broadcast.MiningFeeResponse{ | ||
Bytes: 1000, | ||
Satoshis: 1, | ||
}, | ||
Timestamp: "2023-08-10T13:49:07.308687569Z", | ||
}, | ||
}, | ||
{ | ||
name: "error in HTTP request", | ||
httpError: errors.New("some error"), | ||
expectedError: errors.New("some error"), | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
// given | ||
mockHttpClient := new(MockHttpClient) | ||
|
||
mockHttpClient.On("DoRequest", mock.Anything, mock.Anything). | ||
Return(tc.httpResponse, tc.httpError).Once() | ||
|
||
client := &ArcClient{ | ||
HTTPClient: mockHttpClient, | ||
apiURL: "http://example.com", | ||
token: "someToken", | ||
} | ||
|
||
// when | ||
result, err := client.GetFastestQuote(context.Background(), time.Second) | ||
|
||
// then | ||
assert.Equal(t, tc.expectedResult, result) | ||
assert.Equal(t, tc.expectedError, err) | ||
|
||
// assert Expectations on the mock | ||
mockHttpClient.AssertExpectations(t) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package arc | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/bitcoin-sv/go-broadcast-client/broadcast" | ||
) | ||
|
||
func (a *ArcClient) GetFeeQuote(ctx context.Context) (*broadcast.FeeQuote, error) { | ||
policyQuote, err := a.GetPolicyQuote(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
feeQuote := &broadcast.FeeQuote{ | ||
Miner: a.apiURL, | ||
MiningFee: policyQuote.Policy.MiningFee, | ||
Timestamp: policyQuote.Timestamp, | ||
} | ||
return feeQuote, nil | ||
} |
Oops, something went wrong.