Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
176 commits
Select commit Hold shift + click to select a range
a006163
Slight enhance of Coinbase tests
cranktakular Sep 12, 2023
074f367
Merge branch 'master' into coinbase_api_revamp
cranktakular Oct 8, 2023
bd9f2dd
Coinbase revamp; CreateReport is still WIP
cranktakular Oct 9, 2023
25fcd2e
More coinbase improvements; onto sandbox testing
cranktakular Oct 16, 2023
5d3fd99
Coinbase revamp continues
cranktakular Oct 23, 2023
3aca36b
Coinbase revamp continues
cranktakular Oct 23, 2023
f58b76d
Merge branch 'coinbase_api_revamp' of github.com:cranktakular/gocrypt…
cranktakular Oct 23, 2023
eded160
Coinbasepro revamp is ceaseless
cranktakular Oct 24, 2023
5a0ba23
Coinbase revamp, starting on advanced trade API
cranktakular Nov 1, 2023
88e6713
Coinbase Advanced Trade Starts in Ernest
cranktakular Nov 7, 2023
aa2efef
Coinbase revamp stage wrapper
cranktakular Nov 28, 2023
3560599
Merge branch 'master' into coinbase_api_revamp
cranktakular Nov 28, 2023
4593828
Coinbase wrapper coherence continues
cranktakular Nov 28, 2023
a8cae40
Coinbase wrapper continues writhing
cranktakular Dec 5, 2023
0564e45
Coinbase wrapper & codebase cleanup
cranktakular Dec 11, 2023
4f5ccb5
Coinbase updates & wrap progress
cranktakular Dec 19, 2023
9a6c7e6
More Coinbase wrapper progress
cranktakular Dec 27, 2023
2896b3e
Wrapper is wrapped, kinda
cranktakular Jan 2, 2024
ffb43d8
Test & type checking
cranktakular Jan 9, 2024
7dd4589
Coinbase REST revamp finished
cranktakular Jan 16, 2024
6d7ac5f
Merge branch 'master' into coinbase_api_revamp
cranktakular Jan 16, 2024
2881841
Post-merge fix
cranktakular Jan 16, 2024
2166886
WS revamp begins
cranktakular Jan 16, 2024
35eda67
WS Main Revamp Done?
cranktakular Jan 22, 2024
6ac86cd
CB websocket tidying up
cranktakular Jan 31, 2024
cfe6e11
Coinbase WS wrapperupperer
cranktakular Feb 6, 2024
2f770d5
Coinbase revamp done??
cranktakular Feb 14, 2024
3e54528
Merge branch 'master' into coinbase_api_revamp
cranktakular Feb 14, 2024
2f05c05
Linter progress
cranktakular Feb 20, 2024
005af4a
Continued lint cleanup
cranktakular Feb 20, 2024
2b5df7c
Further lint cleanup
cranktakular Feb 20, 2024
93d6722
Increased lint coverage
cranktakular Feb 20, 2024
529f7f3
Does this fix all sloppy reassigns & shadowing?
cranktakular Feb 20, 2024
8bb2561
Undoing retry policy change
cranktakular Feb 20, 2024
5f813e3
Documentation regeneration
cranktakular Feb 20, 2024
c7d7ac2
Coinbase code improvements
cranktakular Feb 27, 2024
8cdc78a
Providing warning about known issue
cranktakular Feb 27, 2024
19245e3
Merge branch 'master' into coinbase_api_revamp
cranktakular Feb 27, 2024
79ac205
Updating an error to new format
cranktakular Feb 27, 2024
e073757
Making gocritic happy
cranktakular Feb 27, 2024
a65fc38
Review adherence
cranktakular Mar 7, 2024
254efe7
Merge branch 'master' into coinbase_api_revamp
cranktakular Mar 7, 2024
14ab490
Endpoints moved to V3 & nil pointer fixes
cranktakular Mar 7, 2024
bee2878
Removing seemingly superfluous constant
cranktakular Mar 8, 2024
1d51a2e
Glorious improvements
cranktakular Apr 9, 2024
90e20e1
Merge master, resolving conflict
cranktakular Apr 14, 2024
4d1afc2
Removing unused error
cranktakular Apr 14, 2024
55596d8
Partial public endpoint addition
cranktakular Apr 15, 2024
343052b
Slight improvements
cranktakular Apr 22, 2024
ea43046
Wrapper improvements; still a few errors left in other packages
cranktakular Apr 30, 2024
6dbb243
A lil Coinbase progress
cranktakular May 7, 2024
f3fc162
Merge with master + improvements
cranktakular May 7, 2024
a5a3bad
Json cleaning
cranktakular May 7, 2024
742b21e
Lint appeasement
cranktakular May 7, 2024
71e0fa5
Config repair
cranktakular May 7, 2024
01ccd01
Config fix (real)
cranktakular May 7, 2024
228c3ba
Merge master maybe?
cranktakular May 30, 2024
91d4b24
Little fix
cranktakular May 30, 2024
75425fd
New public endpoint incorporation
cranktakular Jun 11, 2024
44ff400
Merge branch 'master' into coinbase_api_revamp
cranktakular Jun 11, 2024
eec8a5d
Additional fixes
cranktakular Jun 11, 2024
bbcc27b
Improvements & Appeasements
cranktakular Jun 11, 2024
e8a06e8
LineSaver
cranktakular Jun 11, 2024
d70d599
Merge branch 'master' into coinbase_api_revamp
cranktakular Jun 18, 2024
4b79d3f
Merge branch 'master' into coinbase_api_revamp
cranktakular Jul 30, 2024
d699631
Additional fixes
cranktakular Jul 30, 2024
0f18f8c
Another fix
cranktakular Jul 30, 2024
c0aa9a4
Fixing picked nits
cranktakular Aug 7, 2024
ac98019
Quick fixies
cranktakular Aug 7, 2024
8e1b87b
Merge branch 'master' into coinbase_api_revamp
cranktakular Aug 13, 2024
e372aea
Lil fixes
cranktakular Aug 13, 2024
d384ec2
Subscriptions: Add List.Enabled
gbjk Aug 23, 2024
9205394
CoinbasePro: Add subscription templating
gbjk Aug 21, 2024
13a3faf
fixup! CoinbasePro: Add subscription templating
gbjk Aug 27, 2024
62c48af
fixup! CoinbasePro: Add subscription templating
gbjk Aug 27, 2024
1dac1c1
Merge pull request #3 from gbjk/feature/coinbase_sub_conf_v2
cranktakular Aug 27, 2024
2e814d5
Comment fix
cranktakular Aug 27, 2024
57567f8
Merge branch 'coinbase_api_revamp' of github.com:cranktakular/gocrypt…
cranktakular Aug 27, 2024
02b88c4
Merge branch 'master' into coinbase_api_revamp
cranktakular Aug 27, 2024
06f8a6a
Subsequent fixes
cranktakular Aug 27, 2024
0e0c09e
Merge branch 'master' into coinbase_api_revamp
cranktakular Sep 2, 2024
9edf0c9
Issues hopefully fixed
cranktakular Sep 3, 2024
7e30794
Lint fix
cranktakular Sep 3, 2024
242efa3
Merge branch 'master' into coinbase_api_revamp
cranktakular Sep 17, 2024
329e039
Glorious fixes
cranktakular Sep 17, 2024
d797e69
Json formatting
cranktakular Sep 17, 2024
9925c88
ShazNits
cranktakular Sep 24, 2024
c88b057
(L/N)i(n/)t
cranktakular Sep 29, 2024
0eeb73c
Merge master and minor fixes
cranktakular Oct 8, 2024
4acb64d
Merge master and minor fixes
cranktakular Oct 16, 2024
5974421
Adding a test
cranktakular Oct 16, 2024
2a90b5d
Tiny test improvement
cranktakular Oct 16, 2024
3f6976c
Merge branch 'master' into coinbase_api_revamp
cranktakular Oct 29, 2024
3eb15db
Template patch testing
cranktakular Nov 5, 2024
38f2765
Fixes
cranktakular Nov 5, 2024
2cc9d0c
Merge branch 'master' into coinbase_api_revamp
cranktakular Nov 5, 2024
2fd8bb1
Further shaznits
cranktakular Nov 12, 2024
1229376
Merge branch 'master' into coinbase_api_revamp
cranktakular Nov 12, 2024
a4252ec
Lint nit
cranktakular Nov 12, 2024
ff6ce5f
JWT move and other fixes
cranktakular Nov 27, 2024
19fbf09
Small nits
cranktakular Dec 3, 2024
e1ba339
Shaznit, singular
cranktakular Dec 11, 2024
59a9d7b
Merge branch 'master' into coinbase_api_revamp
cranktakular Dec 12, 2024
80cb272
Post-merge fix
cranktakular Dec 12, 2024
eba7717
Merge branch 'master' into coinbase_api_revamp
cranktakular Jan 1, 2025
74f47d0
Post-merge fixes
cranktakular Jan 2, 2025
52f1089
Typo fix
cranktakular Jan 2, 2025
0b3de87
Some glorious nits
cranktakular Jan 14, 2025
2350629
Merge branch 'master' into coinbase_api_revamp
cranktakular Jan 14, 2025
3447fea
Required changes
cranktakular Jan 21, 2025
4820d65
Stop going
cranktakular Jan 21, 2025
a316c25
Alias attempt
cranktakular Jan 28, 2025
2e35113
Alias fix & test cleanup
cranktakular Jan 28, 2025
50a599b
Merge branch 'master' into coinbase_api_revamp
cranktakular Jan 28, 2025
5cc49e8
Test fix
cranktakular Jan 28, 2025
0c85038
GetDepositAddress logic improvement
cranktakular Feb 5, 2025
2de2256
Status update: Fixed
cranktakular Feb 5, 2025
ea87268
Lint fix
cranktakular Feb 5, 2025
944b975
Merge branch 'master' into coinbase_api_revamp
cranktakular Feb 10, 2025
00d42b6
Merge branch 'master' into coinbase_api_revamp
cranktakular Feb 10, 2025
e33a655
Happy birthday to PR 1480
cranktakular Feb 20, 2025
5f8f5b5
Merge branch 'master' into coinbase_api_revamp
cranktakular Feb 20, 2025
7d9789e
Cleanups
cranktakular Feb 20, 2025
fb0fe06
Necessary nit corrections
cranktakular Feb 27, 2025
7409cad
Merge branch 'master' into coinbase_api_revamp
cranktakular Feb 27, 2025
5de9d7f
Fixing sillybug
cranktakular Feb 27, 2025
d3bdad0
Merge branch 'master' into coinbase_api_revamp
cranktakular Mar 6, 2025
0d05b24
Quick merge master, worth double-checking test changes I rejected
cranktakular Mar 18, 2025
11ba1e8
As per request
cranktakular Mar 27, 2025
df694fd
Merge branch 'master' into coinbase_api_revamp
cranktakular Mar 27, 2025
d5b9bf3
Programming progress
cranktakular Mar 27, 2025
895efc8
Order fixes
cranktakular Mar 31, 2025
98ca051
Merge branch 'master' into coinbase_api_revamp
cranktakular Mar 31, 2025
7764b9d
Further fixies
cranktakular Mar 31, 2025
e9aeb33
Test fix
cranktakular Mar 31, 2025
51103b7
Pre-merge fixes
cranktakular Apr 7, 2025
1c5b1ed
Merge & fixes
cranktakular Apr 7, 2025
ecbbbc0
Merge branch 'master' into coinbase_api_revamp
cranktakular Apr 15, 2025
4bf0d1f
More shaznits
cranktakular Apr 15, 2025
64cfc62
Context
cranktakular Apr 15, 2025
13d8746
Sonic error handling
cranktakular Apr 15, 2025
bb68ccf
Import fix
cranktakular Apr 15, 2025
5fc1bbd
Better Sonic error handling
cranktakular Apr 15, 2025
404cda8
Perfect Sonic error handling?
cranktakular Apr 15, 2025
d4eaf58
F purge
cranktakular Apr 15, 2025
10e0212
Coinbase improvements
cranktakular Apr 22, 2025
7743a7f
API Update Conformity
cranktakular Apr 29, 2025
ae47e3d
Merge branch 'master' into coinbase_api_revamp
cranktakular May 13, 2025
cdc2447
Coinbase continuation
cranktakular May 13, 2025
18b134c
Merge and associated fixes
cranktakular Jun 10, 2025
c3d7edb
Coinbase order improvements
cranktakular Jun 10, 2025
639d7db
Coinbase order improvements
cranktakular Jun 10, 2025
a8d41ea
CreateOrderConfig improvements
cranktakular Jun 24, 2025
6a408b7
Merge branch 'master' into coinbase_api_revamp
cranktakular Jul 1, 2025
82e9215
Managing API updates
cranktakular Jul 1, 2025
f2707ac
Coinbase API update progression
cranktakular Jul 8, 2025
3fa8da5
jwt rename
cranktakular Jul 15, 2025
511720e
Comment link fix
cranktakular Jul 15, 2025
b2f5a83
Coinbase v2 cleanup
cranktakular Jul 15, 2025
9396618
Merge branch 'master' into coinbase_api_revamp
cranktakular Aug 5, 2025
3dcd419
Post-merge fixes
cranktakular Aug 5, 2025
04d2218
Review fixes
cranktakular Aug 12, 2025
c008869
GK's suggestions
cranktakular Aug 19, 2025
c2726b9
Merge branch 'master' into coinbase_api_revamp
cranktakular Aug 19, 2025
330e848
Linter fix
cranktakular Aug 19, 2025
2e685ce
Minor gbjk fixes
cranktakular Aug 19, 2025
0411e46
Nit fixes
cranktakular Aug 26, 2025
6651cda
Merge branch 'master' into coinbase_api_revamp
cranktakular Aug 26, 2025
587eefd
Merge fix
cranktakular Aug 26, 2025
2e5b6fe
Lint fixes
cranktakular Aug 26, 2025
1ff7838
Merge branch 'master' into coinbase_api_revamp
cranktakular Aug 26, 2025
8a1a020
Coinbase rename stage 1
cranktakular Aug 26, 2025
bd69baa
Coinbase rename stage 2
cranktakular Aug 26, 2025
fce9f4e
Coinbase rename stage 3
cranktakular Aug 26, 2025
a13ce5b
Coinbase rename stage 4
cranktakular Aug 26, 2025
b16b543
Coinbase rename final fix
cranktakular Aug 26, 2025
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
91 changes: 47 additions & 44 deletions exchanges/coinbasepro/coinbasepro.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ const (
startDateString = "start_date"
endDateString = "end_date"

warnSequenceIssue = "Out of order sequence number. Received %v, expected %v"
warnAuth = "%v authenticated request failed, attempting unauthenticated"
warnAuth = "%v authenticated request failed, attempting unauthenticated"

defaultOrderFillCount = 3000 // Largest number of fills the exchange will let one retrieve in a request, found through experimentation
defaultOrderCount = 2147483647 // int32 limit, largest number of orders the exchange will let one retrieve in a request, found through experimentation
Expand Down Expand Up @@ -154,6 +153,7 @@ var (
errMarginProfileTypeEmpty = errors.New("margin profile type cannot be empty")
errSettingEmpty = errors.New("setting cannot be empty")
errUnknownTransferType = errors.New("unknown transfer type")
errOutOfSequence = errors.New("out of order sequence number")

closedStatuses = []string{"FILLED", "CANCELLED", "EXPIRED", "FAILED"}
openStatus = []string{"OPEN"}
Expand Down Expand Up @@ -416,7 +416,7 @@ func (e *Exchange) PlaceOrder(ctx context.Context, ord *PlaceOrderInfo) (*Succes
if ord.BaseAmount <= 0 {
return nil, order.ErrAmountIsInvalid
}
orderConfig, err := createOrderConfig(ord.OrderType, ord.TimeInForce, ord.StopDirection, ord.BaseAmount, ord.QuoteAmount, ord.LimitPrice, ord.StopPrice, ord.BucketSize, ord.EndTime, ord.PostOnly, ord.RFQDisabled, ord.BucketNumber, ord.BucketDuration)
orderConfig, err := createOrderConfig(&ord.SharedOrderConfig)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -577,7 +577,7 @@ func (e *Exchange) PreviewOrder(ctx context.Context, inf *PreviewOrderInfo) (*Pr
if inf.BaseAmount <= 0 && inf.QuoteAmount <= 0 {
return nil, order.ErrAmountIsInvalid
}
orderConfig, err := createOrderConfig(inf.OrderType, inf.TimeInForce, inf.StopDirection, inf.BaseAmount, inf.QuoteAmount, inf.LimitPrice, inf.StopPrice, inf.BucketSize, inf.EndTime, inf.PostOnly, inf.RFQDisabled, inf.BucketNumber, inf.BucketDuration)
orderConfig, err := createOrderConfig(&inf.SharedOrderConfig)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1636,76 +1636,79 @@ func (p *Params) encodePagination(pag PaginationInp) error {
}

// createOrderConfig populates the OrderConfiguration struct
func createOrderConfig(orderType order.Type, timeInForce order.TimeInForce, stopDirection string, baseAmount, quoteAmount, limitPrice, stopPrice, bucketSize float64, endTime time.Time, postOnly, rfqDisabled bool, bucketNumber int64, bucketDuration time.Duration) (OrderConfiguration, error) {
func createOrderConfig(sharedParams *SharedOrderConfig) (OrderConfiguration, error) {
if sharedParams == nil {
return OrderConfiguration{}, fmt.Errorf("%T %w", sharedParams, common.ErrNilPointer)
}
var orderConfig OrderConfiguration
switch orderType {
switch sharedParams.OrderType {
case order.Market:
if baseAmount != 0 {
orderConfig.MarketMarketIOC = &MarketMarketIOC{BaseSize: types.Number(baseAmount), RFQDisabled: rfqDisabled}
if sharedParams.BaseAmount != 0 {
orderConfig.MarketMarketIOC = &MarketMarketIOC{BaseSize: types.Number(sharedParams.BaseAmount), RFQDisabled: sharedParams.RFQDisabled}
}
if quoteAmount != 0 {
orderConfig.MarketMarketIOC = &MarketMarketIOC{QuoteSize: types.Number(quoteAmount), RFQDisabled: rfqDisabled}
if sharedParams.QuoteAmount != 0 {
orderConfig.MarketMarketIOC = &MarketMarketIOC{QuoteSize: types.Number(sharedParams.QuoteAmount), RFQDisabled: sharedParams.RFQDisabled}
}
case order.Limit:
switch {
case timeInForce == order.StopOrReduce:
orderConfig.SORLimitIOC = &QuoteBaseLimit{BaseSize: types.Number(baseAmount), QuoteSize: types.Number(quoteAmount), LimitPrice: types.Number(limitPrice), RFQDisabled: rfqDisabled}
case timeInForce == order.FillOrKill:
orderConfig.LimitLimitFOK = &QuoteBaseLimit{BaseSize: types.Number(baseAmount), QuoteSize: types.Number(quoteAmount), LimitPrice: types.Number(limitPrice), RFQDisabled: rfqDisabled}
case endTime.IsZero():
orderConfig.LimitLimitGTC = &LimitLimitGTC{LimitPrice: types.Number(limitPrice), PostOnly: postOnly, RFQDisabled: rfqDisabled}
if baseAmount != 0 {
orderConfig.LimitLimitGTC.BaseSize = types.Number(baseAmount)
case sharedParams.TimeInForce == order.StopOrReduce:
orderConfig.SORLimitIOC = &QuoteBaseLimit{BaseSize: types.Number(sharedParams.BaseAmount), QuoteSize: types.Number(sharedParams.QuoteAmount), LimitPrice: types.Number(sharedParams.LimitPrice), RFQDisabled: sharedParams.RFQDisabled}
case sharedParams.TimeInForce == order.FillOrKill:
orderConfig.LimitLimitFOK = &QuoteBaseLimit{BaseSize: types.Number(sharedParams.BaseAmount), QuoteSize: types.Number(sharedParams.QuoteAmount), LimitPrice: types.Number(sharedParams.LimitPrice), RFQDisabled: sharedParams.RFQDisabled}
case sharedParams.EndTime.IsZero():
orderConfig.LimitLimitGTC = &LimitLimitGTC{LimitPrice: types.Number(sharedParams.LimitPrice), PostOnly: sharedParams.PostOnly, RFQDisabled: sharedParams.RFQDisabled}
if sharedParams.BaseAmount != 0 {
orderConfig.LimitLimitGTC.BaseSize = types.Number(sharedParams.BaseAmount)
}
if quoteAmount != 0 {
orderConfig.LimitLimitGTC.QuoteSize = types.Number(quoteAmount)
if sharedParams.QuoteAmount != 0 {
orderConfig.LimitLimitGTC.QuoteSize = types.Number(sharedParams.QuoteAmount)
}
default:
if endTime.Before(time.Now()) {
if sharedParams.EndTime.Before(time.Now()) {
return orderConfig, errEndTimeInPast
}
orderConfig.LimitLimitGTD = &LimitLimitGTD{LimitPrice: types.Number(limitPrice), PostOnly: postOnly, EndTime: endTime, RFQDisabled: rfqDisabled}
if baseAmount != 0 {
orderConfig.LimitLimitGTD.BaseSize = types.Number(baseAmount)
orderConfig.LimitLimitGTD = &LimitLimitGTD{LimitPrice: types.Number(sharedParams.LimitPrice), PostOnly: sharedParams.PostOnly, EndTime: sharedParams.EndTime, RFQDisabled: sharedParams.RFQDisabled}
if sharedParams.BaseAmount != 0 {
orderConfig.LimitLimitGTD.BaseSize = types.Number(sharedParams.BaseAmount)
}
if quoteAmount != 0 {
orderConfig.LimitLimitGTD.QuoteSize = types.Number(quoteAmount)
if sharedParams.QuoteAmount != 0 {
orderConfig.LimitLimitGTD.QuoteSize = types.Number(sharedParams.QuoteAmount)
}
}
case order.TWAP:
if endTime.Before(time.Now()) {
if sharedParams.EndTime.Before(time.Now()) {
return orderConfig, errEndTimeInPast
}
orderConfig.TWAPLimitGTD = &TWAPLimitGTD{StartTime: time.Now(), EndTime: endTime, LimitPrice: types.Number(limitPrice), NumberBuckets: bucketNumber, BucketSize: types.Number(bucketSize), BucketDuration: strconv.FormatFloat(bucketDuration.Seconds(), 'f', -1, 64) + "s"}
orderConfig.TWAPLimitGTD = &TWAPLimitGTD{StartTime: time.Now(), EndTime: sharedParams.EndTime, LimitPrice: types.Number(sharedParams.LimitPrice), NumberBuckets: sharedParams.BucketNumber, BucketSize: types.Number(sharedParams.BucketSize), BucketDuration: strconv.FormatFloat(sharedParams.BucketDuration.Seconds(), 'f', -1, 64) + "s"}
case order.StopLimit:
if endTime.IsZero() {
orderConfig.StopLimitStopLimitGTC = &StopLimitStopLimitGTC{LimitPrice: types.Number(limitPrice), StopPrice: types.Number(stopPrice), StopDirection: stopDirection}
if baseAmount != 0 {
orderConfig.StopLimitStopLimitGTC.BaseSize = types.Number(baseAmount)
if sharedParams.EndTime.IsZero() {
orderConfig.StopLimitStopLimitGTC = &StopLimitStopLimitGTC{LimitPrice: types.Number(sharedParams.LimitPrice), StopPrice: types.Number(sharedParams.StopPrice), StopDirection: sharedParams.StopDirection}
if sharedParams.BaseAmount != 0 {
orderConfig.StopLimitStopLimitGTC.BaseSize = types.Number(sharedParams.BaseAmount)
}
if quoteAmount != 0 {
orderConfig.StopLimitStopLimitGTC.QuoteSize = types.Number(quoteAmount)
if sharedParams.QuoteAmount != 0 {
orderConfig.StopLimitStopLimitGTC.QuoteSize = types.Number(sharedParams.QuoteAmount)
}
} else {
if endTime.Before(time.Now()) {
if sharedParams.EndTime.Before(time.Now()) {
return orderConfig, errEndTimeInPast
}
orderConfig.StopLimitStopLimitGTD = &StopLimitStopLimitGTD{LimitPrice: types.Number(limitPrice), StopPrice: types.Number(stopPrice), StopDirection: stopDirection, EndTime: endTime}
if baseAmount != 0 {
orderConfig.StopLimitStopLimitGTD.BaseSize = types.Number(baseAmount)
orderConfig.StopLimitStopLimitGTD = &StopLimitStopLimitGTD{LimitPrice: types.Number(sharedParams.LimitPrice), StopPrice: types.Number(sharedParams.StopPrice), StopDirection: sharedParams.StopDirection, EndTime: sharedParams.EndTime}
if sharedParams.BaseAmount != 0 {
orderConfig.StopLimitStopLimitGTD.BaseSize = types.Number(sharedParams.BaseAmount)
}
if quoteAmount != 0 {
orderConfig.StopLimitStopLimitGTD.QuoteSize = types.Number(quoteAmount)
if sharedParams.QuoteAmount != 0 {
orderConfig.StopLimitStopLimitGTD.QuoteSize = types.Number(sharedParams.QuoteAmount)
}
}
case order.Bracket:
if endTime.IsZero() {
orderConfig.TriggerBracketGTC = &TriggerBracketGTC{BaseSize: types.Number(baseAmount), LimitPrice: types.Number(limitPrice), StopTriggerPrice: types.Number(stopPrice)}
if sharedParams.EndTime.IsZero() {
orderConfig.TriggerBracketGTC = &TriggerBracketGTC{BaseSize: types.Number(sharedParams.BaseAmount), LimitPrice: types.Number(sharedParams.LimitPrice), StopTriggerPrice: types.Number(sharedParams.StopPrice)}
} else {
if endTime.Before(time.Now()) {
if sharedParams.EndTime.Before(time.Now()) {
return orderConfig, errEndTimeInPast
}
orderConfig.TriggerBracketGTD = &TriggerBracketGTD{BaseSize: types.Number(baseAmount), LimitPrice: types.Number(limitPrice), StopTriggerPrice: types.Number(stopPrice), EndTime: endTime}
orderConfig.TriggerBracketGTD = &TriggerBracketGTD{BaseSize: types.Number(sharedParams.BaseAmount), LimitPrice: types.Number(sharedParams.LimitPrice), StopTriggerPrice: types.Number(sharedParams.StopPrice), EndTime: sharedParams.EndTime}
}
default:
return orderConfig, errInvalidOrderType
Expand Down
66 changes: 44 additions & 22 deletions exchanges/coinbasepro/coinbasepro_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,15 @@ func TestPlaceOrder(t *testing.T) {
ClientOID: id.String(),
ProductID: testPairStable.String(),
Side: order.Buy.String(),
OrderType: order.Limit,
MarginType: "CROSS",
BaseAmount: testAmount,
LimitPrice: testPrice2,
Leverage: 9999,
PostOnly: false,
EndTime: time.Now().Add(time.Hour),
SharedOrderConfig: SharedOrderConfig{
PostOnly: false,
EndTime: time.Now().Add(time.Hour),
OrderType: order.Limit,
BaseAmount: testAmount,
LimitPrice: testPrice2,
},
}
resp, err := e.PlaceOrder(t.Context(), ord)
if assert.NoError(t, err) {
Expand Down Expand Up @@ -1622,7 +1624,7 @@ func TestWsHandleData(t *testing.T) {
mockJSON = []byte(`{"sequence_num": 0, "channel": "user", "events": [{"type": false}]}`)
_, err = e.wsHandleData(mockJSON)
assert.True(t, errors.As(err, &unmarshalTypeErr) || strings.Contains(err.Error(), "mismatched type with value"), errJSONUnmarshalUnexpected)
mockJSON = []byte(`{"sequence_num": 0, "channel": "user", "events": [{"type": "moo", "orders": [{"limit_price": "2.2", "total_fees": "1.1"}], "positions": {"perpetual_futures_positions": [{"margin_type": "fakeMarginType"}], "expiring_futures_positions": [{}]}}]}`)
mockJSON = []byte(`{"sequence_num": 0, "channel": "user", "events": [{"type": "moo", "orders": [{"limit_price": "2.2", "total_fees": "1.1", "post_only": true}], "positions": {"perpetual_futures_positions": [{"margin_type": "fakeMarginType"}], "expiring_futures_positions": [{}]}}]}`)
_, err = e.wsHandleData(mockJSON)
assert.NoError(t, err)
mockJSON = []byte(`{"sequence_num": 0, "channel": "fakechan", "events": [{"type": ""}]}`)
Expand Down Expand Up @@ -1758,35 +1760,55 @@ func TestEncodePagination(t *testing.T) {

func TestCreateOrderConfig(t *testing.T) {
t.Parallel()
_, err := createOrderConfig(order.UnknownType, order.UnknownTIF, "", 0, 0, 0, 0, 0, time.Time{}, false, false, 0, 0)
_, err := createOrderConfig(nil)
assert.ErrorIs(t, err, common.ErrNilPointer)
params := &SharedOrderConfig{}
_, err = createOrderConfig(params)
assert.ErrorIs(t, err, errInvalidOrderType)
_, err = createOrderConfig(order.Market, order.UnknownTIF, "", 1, 2, 0, 0, 0, time.Time{}, false, false, 0, 0)
params.BaseAmount = 1
params.QuoteAmount = 2
params.OrderType = order.Market
_, err = createOrderConfig(params)
assert.NoError(t, err)
_, err = createOrderConfig(order.Limit, order.StopOrReduce, "", 1, 2, 0, 0, 0, time.Time{}, false, false, 0, 0)
params.OrderType = order.Limit
params.TimeInForce = order.StopOrReduce
_, err = createOrderConfig(params)
assert.NoError(t, err)
_, err = createOrderConfig(order.Limit, order.UnknownTIF, "", 1, 2, 0, 0, 0, time.Time{}, false, false, 0, 0)
params.TimeInForce = order.FillOrKill
_, err = createOrderConfig(params)
assert.NoError(t, err)
_, err = createOrderConfig(order.Limit, order.FillOrKill, "", 1, 2, 0, 0, 0, time.Time{}, false, false, 0, 0)
params.TimeInForce = order.UnknownTIF
_, err = createOrderConfig(params)
assert.NoError(t, err)
_, err = createOrderConfig(order.Limit, order.UnknownTIF, "", 0, 0, 0, 0, 0, time.Unix(1, 1), false, false, 0, 0)
params.EndTime = time.Unix(1, 1)
_, err = createOrderConfig(params)
assert.ErrorIs(t, err, errEndTimeInPast)
_, err = createOrderConfig(order.Limit, order.UnknownTIF, "", 1, 2, 0, 0, 0, time.Now().Add(time.Hour), false, false, 0, 0)
params.EndTime = time.Now().Add(time.Hour)
_, err = createOrderConfig(params)
assert.NoError(t, err)
_, err = createOrderConfig(order.TWAP, order.UnknownTIF, "", 1, 2, 0, 0, 0, time.Time{}, false, false, 0, 0)
assert.ErrorIs(t, err, errEndTimeInPast)
_, err = createOrderConfig(order.TWAP, order.UnknownTIF, "", 1, 2, 0, 0, 0, time.Now().Add(time.Hour), false, false, 0, 0)
params.OrderType = order.TWAP
_, err = createOrderConfig(params)
assert.NoError(t, err)
_, err = createOrderConfig(order.StopLimit, order.UnknownTIF, "", 1, 2, 0, 0, 0, time.Time{}, false, false, 0, 0)
params.EndTime = time.Time{}
_, err = createOrderConfig(params)
assert.ErrorIs(t, err, errEndTimeInPast)
params.OrderType = order.StopLimit
_, err = createOrderConfig(params)
assert.NoError(t, err)
_, err = createOrderConfig(order.StopLimit, order.UnknownTIF, "", 0, 0, 0, 0, 0, time.Unix(1, 1), false, false, 0, 0)
params.EndTime = time.Unix(1, 1)
_, err = createOrderConfig(params)
assert.ErrorIs(t, err, errEndTimeInPast)
_, err = createOrderConfig(order.StopLimit, order.UnknownTIF, "", 1, 2, 0, 0, 0, time.Now().Add(time.Hour), false, false, 0, 0)
params.EndTime = time.Now().Add(time.Hour)
_, err = createOrderConfig(params)
assert.NoError(t, err)
_, err = createOrderConfig(order.Bracket, order.UnknownTIF, "", 1, 2, 0, 0, 0, time.Time{}, false, false, 0, 0)
params.OrderType = order.Bracket
_, err = createOrderConfig(params)
assert.NoError(t, err)
_, err = createOrderConfig(order.Bracket, order.UnknownTIF, "", 0, 0, 0, 0, 0, time.Unix(1, 1), false, false, 0, 0)
params.EndTime = time.Unix(1, 1)
_, err = createOrderConfig(params)
assert.ErrorIs(t, err, errEndTimeInPast)
_, err = createOrderConfig(order.Bracket, order.UnknownTIF, "", 1, 2, 0, 0, 0, time.Now().Add(time.Hour), false, false, 0, 0)
params.EndTime = time.Time{}
_, err = createOrderConfig(params)
assert.NoError(t, err)
}

Expand Down
45 changes: 19 additions & 26 deletions exchanges/coinbasepro/coinbasepro_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,29 +365,34 @@ type ErrorResponse struct {
NewOrderFailureReason string `json:"new_order_failure_reason"`
}

// SharedOrderConfig contains order configuration information used in both PlaceOrderInfo and PreviewOrderInfo
type SharedOrderConfig struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦍 I don't think we need to say it's shared. It's just OrderConfig.
I think you're only thinking about it being shared because of where you started.

Suggested change
type SharedOrderConfig struct {
type OrderConfig struct {

Do not need to action.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's already an OrderConfiguration type, which contains the full, properly-formatted depth of information. Typing that out, "shared" isn't the right way to distinguish this, but the other ideas I have (OrderConfigPreparation, OrderConfigConstructor) seem more verbose and also a bit wrong.

I do think that just "OrderConfig" is a bit close for comfort.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, that would not fly.

  • OrderConfiguration smells like OrderType or OrderConds
    Everything in there is about order type conditions.

  • SharedOrderConfig lives in 2 structs named *OrderInfo. So I think it's actually just OrderInfo 😄

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OrderConfiguration naming comes from what the exchange itself calls it. Would like to double-check changing it.

But I'll apply that change from SharedOrderConfig > OrderInfo.

OrderType order.Type
TimeInForce order.TimeInForce
StopDirection string
BaseAmount float64
QuoteAmount float64
LimitPrice float64
StopPrice float64
BucketSize float64
EndTime time.Time
PostOnly bool
RFQDisabled bool
BucketNumber int64
BucketDuration time.Duration
}

// PlaceOrderInfo is a struct used in the formation of requests in PlaceOrder
type PlaceOrderInfo struct {
ClientOID string
ProductID string
Side string
StopDirection string
OrderType order.Type
TimeInForce order.TimeInForce
MarginType string
RetailPortfolioID string
PreviewID string
BaseAmount float64
QuoteAmount float64
LimitPrice float64
StopPrice float64
Leverage float64
PostOnly bool
RFQDisabled bool
EndTime time.Time
BucketSize float64
BucketNumber int64
BucketDuration time.Duration
AttachedOrderConfiguration OrderConfiguration
SharedOrderConfig
}

// SuccessFailureConfig contains information on an order, returned by PlaceOrder
Expand Down Expand Up @@ -499,23 +504,11 @@ type FillResponse struct {
type PreviewOrderInfo struct {
ProductID string
Side string
OrderType order.Type
TimeInForce order.TimeInForce
StopDirection string
MarginType string
RetailPortfolioID string
BaseAmount float64
QuoteAmount float64
LimitPrice float64
StopPrice float64
Leverage float64
BucketSize float64
BucketNumber int64
BucketDuration time.Duration
PostOnly bool
RFQDisabled bool
EndTime time.Time
AttachedOrderConfiguration OrderConfiguration
SharedOrderConfig
}

// TriggerBracketPNL is a sub-struct used in the type PreviewOrderResp
Expand Down
Loading
Loading