mirror of
https://github.com/hanzo-fi/payments.git
synced 2026-10-30 20:31:20 +00:00
187 lines
5.9 KiB
Go
187 lines
5.9 KiB
Go
package bitstamp
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/hanzo-fi/go-libs/v5/pkg/observe/log"
|
|
"github.com/hanzo-fi/payments/ee/plugins/bitstamp/client"
|
|
"github.com/hanzo-fi/payments/ee/plugins/bitstamp/mappers"
|
|
"github.com/hanzo-fi/payments/pkg/domain/plugins"
|
|
"github.com/hanzo-fi/payments/pkg/domain/models"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"go.uber.org/mock/gomock"
|
|
)
|
|
|
|
var _ = Describe("Bitstamp Plugin Accounts", func() {
|
|
var (
|
|
ctrl *gomock.Controller
|
|
m *client.MockClient
|
|
plg *Plugin
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
ctrl = gomock.NewController(GinkgoT())
|
|
m = client.NewMockClient(ctrl)
|
|
plg = &Plugin{
|
|
Plugin: plugins.NewBasePlugin(),
|
|
client: m,
|
|
logger: logging.NewDefaultLogger(GinkgoWriter, true, false, false),
|
|
}
|
|
// Enrichment caches are refreshed on every FetchNextAccounts cycle;
|
|
// default each install-time call to a non-empty but cheap response.
|
|
// Per-test cases can override with explicit expectations.
|
|
m.EXPECT().GetMarkets(gomock.Any()).Return(nil, nil).AnyTimes()
|
|
m.EXPECT().GetMyMarkets(gomock.Any()).Return(nil, nil).AnyTimes()
|
|
m.EXPECT().GetTradingFees(gomock.Any()).Return(nil, nil).AnyTimes()
|
|
m.EXPECT().GetWithdrawalFees(gomock.Any()).Return(nil, nil).AnyTimes()
|
|
// currenciesIndex re-fetches full Currency objects on each cycle.
|
|
m.EXPECT().GetCurrencies(gomock.Any()).Return([]client.Currency{
|
|
{Currency: "btc", Decimals: 8},
|
|
{Currency: "usd", Decimals: 2},
|
|
{Currency: "eur", Decimals: 2},
|
|
{Currency: "eth", Decimals: 18},
|
|
}, nil).AnyTimes()
|
|
})
|
|
|
|
AfterEach(func() {
|
|
ctrl.Finish()
|
|
})
|
|
|
|
Context("fetching next accounts", func() {
|
|
It("should return an error - get balances error", func(ctx SpecContext) {
|
|
req := models.FetchNextAccountsRequest{
|
|
State: []byte(`{}`),
|
|
PageSize: 10,
|
|
}
|
|
|
|
m.EXPECT().GetAccountBalances(gomock.Any()).Return(
|
|
nil,
|
|
errors.New("test error"),
|
|
)
|
|
|
|
resp, err := plg.FetchNextAccounts(ctx, req)
|
|
Expect(err).ToNot(BeNil())
|
|
// Orchestrator wraps client errors with a single line of context.
|
|
Expect(err.Error()).To(ContainSubstring("test error"))
|
|
Expect(err.Error()).To(ContainSubstring("fetch accounts"))
|
|
Expect(resp).To(Equal(models.FetchNextAccountsResponse{}))
|
|
})
|
|
|
|
It("should fetch accounts successfully", func(ctx SpecContext) {
|
|
req := models.FetchNextAccountsRequest{
|
|
State: []byte(`{}`),
|
|
PageSize: 10,
|
|
}
|
|
|
|
m.EXPECT().GetAccountBalances(gomock.Any()).Return(
|
|
[]client.AccountBalance{
|
|
{Currency: "btc", Total: "1.50000000", Available: "1.00000000", Reserved: "0.50000000"},
|
|
{Currency: "usd", Total: "5000.00", Available: "4500.00", Reserved: "500.00"},
|
|
{Currency: "eth", Total: "10.000000000000000000", Available: "10.000000000000000000", Reserved: "0"},
|
|
},
|
|
nil,
|
|
)
|
|
|
|
resp, err := plg.FetchNextAccounts(ctx, req)
|
|
Expect(err).To(BeNil())
|
|
Expect(resp.Accounts).To(HaveLen(3))
|
|
Expect(resp.HasMore).To(BeFalse())
|
|
|
|
// Verify BTC account
|
|
Expect(resp.Accounts[0].Reference).To(Equal("BTC"))
|
|
Expect(resp.Accounts[0].CreatedAt).To(Equal(mappers.BitstampGenesis))
|
|
Expect(resp.Accounts[0].Name).NotTo(BeNil())
|
|
Expect(*resp.Accounts[0].Name).To(Equal("BTC"))
|
|
Expect(*resp.Accounts[0].DefaultAsset).To(Equal("BTC/8"))
|
|
|
|
// Verify USD account
|
|
Expect(resp.Accounts[1].Reference).To(Equal("USD"))
|
|
Expect(*resp.Accounts[1].DefaultAsset).To(Equal("USD/2"))
|
|
|
|
// Verify ETH account
|
|
Expect(resp.Accounts[2].Reference).To(Equal("ETH"))
|
|
Expect(*resp.Accounts[2].DefaultAsset).To(Equal("ETH/18"))
|
|
})
|
|
|
|
It("should skip zero-balance currencies", func(ctx SpecContext) {
|
|
req := models.FetchNextAccountsRequest{
|
|
State: []byte(`{}`),
|
|
PageSize: 10,
|
|
}
|
|
|
|
m.EXPECT().GetAccountBalances(gomock.Any()).Return(
|
|
[]client.AccountBalance{
|
|
{Currency: "btc", Total: "1.00000000", Available: "1.00000000", Reserved: "0"},
|
|
{Currency: "usd", Total: "0", Available: "0", Reserved: "0"},
|
|
},
|
|
nil,
|
|
)
|
|
|
|
resp, err := plg.FetchNextAccounts(ctx, req)
|
|
Expect(err).To(BeNil())
|
|
Expect(resp.Accounts).To(HaveLen(1))
|
|
Expect(resp.Accounts[0].Reference).To(Equal("BTC"))
|
|
})
|
|
|
|
It("should keep unsupported currencies without a default asset", func(ctx SpecContext) {
|
|
req := models.FetchNextAccountsRequest{
|
|
State: []byte(`{}`),
|
|
PageSize: 10,
|
|
}
|
|
|
|
m.EXPECT().GetAccountBalances(gomock.Any()).Return(
|
|
[]client.AccountBalance{
|
|
{Currency: "unknown_coin", Total: "100", Available: "100", Reserved: "0"},
|
|
{Currency: "btc", Total: "1.00000000", Available: "1.00000000", Reserved: "0"},
|
|
},
|
|
nil,
|
|
)
|
|
|
|
resp, err := plg.FetchNextAccounts(ctx, req)
|
|
Expect(err).To(BeNil())
|
|
Expect(resp.Accounts).To(HaveLen(2))
|
|
Expect(resp.Accounts[0].Reference).To(Equal("UNKNOWN_COIN"))
|
|
Expect(resp.Accounts[0].DefaultAsset).To(BeNil())
|
|
Expect(resp.Accounts[1].Reference).To(Equal("BTC"))
|
|
})
|
|
|
|
It("should handle empty response", func(ctx SpecContext) {
|
|
req := models.FetchNextAccountsRequest{
|
|
State: []byte(`{}`),
|
|
PageSize: 10,
|
|
}
|
|
|
|
m.EXPECT().GetAccountBalances(gomock.Any()).Return(
|
|
[]client.AccountBalance{},
|
|
nil,
|
|
)
|
|
|
|
resp, err := plg.FetchNextAccounts(ctx, req)
|
|
Expect(err).To(BeNil())
|
|
Expect(resp.Accounts).To(HaveLen(0))
|
|
Expect(resp.HasMore).To(BeFalse())
|
|
})
|
|
|
|
It("should return empty accounts when all currencies were already seen", func(ctx SpecContext) {
|
|
req := models.FetchNextAccountsRequest{
|
|
State: []byte(`{"accountCurrenciesImportedAt":{"BTC":"2025-01-01 00:00:00 +0000 UTC","USD":"2025-01-01 00:00:00 +0000 UTC"}}`),
|
|
PageSize: 10,
|
|
}
|
|
|
|
m.EXPECT().GetAccountBalances(gomock.Any()).Return(
|
|
[]client.AccountBalance{
|
|
{Currency: "btc", Total: "1.50000000", Available: "1.00000000", Reserved: "0.50000000"},
|
|
{Currency: "usd", Total: "5000.00", Available: "4500.00", Reserved: "500.00"},
|
|
},
|
|
nil,
|
|
)
|
|
|
|
resp, err := plg.FetchNextAccounts(ctx, req)
|
|
Expect(err).To(BeNil())
|
|
Expect(resp.Accounts).To(BeEmpty())
|
|
Expect(resp.HasMore).To(BeFalse())
|
|
})
|
|
})
|
|
})
|