diff --git a/api/gateway/aurora/go.mod b/api/gateway/aurora/go.mod index 7c9b1cc4..024ea006 100644 --- a/api/gateway/aurora/go.mod +++ b/api/gateway/aurora/go.mod @@ -14,7 +14,7 @@ require ( github.com/tech/sendico/pkg v0.1.0 go.mongodb.org/mongo-driver/v2 v2.5.0 go.uber.org/zap v1.27.1 - google.golang.org/grpc v1.79.1 + google.golang.org/grpc v1.79.2 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/api/gateway/aurora/go.sum b/api/gateway/aurora/go.sum index bd4681c8..7f875b26 100644 --- a/api/gateway/aurora/go.sum +++ b/api/gateway/aurora/go.sum @@ -212,8 +212,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= -google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU= +google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/api/gateway/chain/client/client.go b/api/gateway/chain/client/client.go index 3581b3d2..2c2babf1 100644 --- a/api/gateway/chain/client/client.go +++ b/api/gateway/chain/client/client.go @@ -492,6 +492,9 @@ func transferFromReceipt(req *chainv1.SubmitTransferRequest, receipt *connectorv transfer.Destination = req.GetDestination() transfer.RequestedAmount = req.GetAmount() transfer.NetAmount = req.GetAmount() + transfer.IntentRef = strings.TrimSpace(req.GetIntentRef()) + transfer.OperationRef = strings.TrimSpace(req.GetOperationRef()) + transfer.PaymentRef = strings.TrimSpace(req.GetPaymentRef()) } if receipt != nil { transfer.TransferRef = strings.TrimSpace(receipt.GetOperationId()) diff --git a/api/gateway/chain/client/client_test.go b/api/gateway/chain/client/client_test.go index f32d0d95..99ba66c8 100644 --- a/api/gateway/chain/client/client_test.go +++ b/api/gateway/chain/client/client_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/require" + moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1" connectorv1 "github.com/tech/sendico/pkg/proto/connector/v1" chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1" "google.golang.org/grpc" @@ -13,6 +14,11 @@ import ( type stubConnectorClient struct { listReq *connectorv1.ListAccountsRequest + getReq *connectorv1.GetOperationRequest + + submitReq *connectorv1.SubmitOperationRequest + submitResp *connectorv1.SubmitOperationResponse + getResp *connectorv1.GetOperationResponse } func (s *stubConnectorClient) GetCapabilities(ctx context.Context, in *connectorv1.GetCapabilitiesRequest, opts ...grpc.CallOption) (*connectorv1.GetCapabilitiesResponse, error) { @@ -37,10 +43,18 @@ func (s *stubConnectorClient) GetBalance(ctx context.Context, in *connectorv1.Ge } func (s *stubConnectorClient) SubmitOperation(ctx context.Context, in *connectorv1.SubmitOperationRequest, opts ...grpc.CallOption) (*connectorv1.SubmitOperationResponse, error) { + s.submitReq = in + if s.submitResp != nil { + return s.submitResp, nil + } return &connectorv1.SubmitOperationResponse{}, nil } func (s *stubConnectorClient) GetOperation(ctx context.Context, in *connectorv1.GetOperationRequest, opts ...grpc.CallOption) (*connectorv1.GetOperationResponse, error) { + s.getReq = in + if s.getResp != nil { + return s.getResp, nil + } return &connectorv1.GetOperationResponse{}, nil } @@ -66,3 +80,84 @@ func TestListManagedWallets_ForwardsOrganizationRef(t *testing.T) { require.Equal(t, "owner-1", stub.listReq.GetOwnerRefFilter().GetValue()) require.Equal(t, connectorv1.AccountKind_CHAIN_MANAGED_WALLET, stub.listReq.GetKind()) } + +func TestTransferFromReceipt_PreservesRequestReferences(t *testing.T) { + req := &chainv1.SubmitTransferRequest{ + IdempotencyKey: "idem-1", + OrganizationRef: "org-1", + SourceWalletRef: "wallet-src", + Amount: &moneyv1.Money{Amount: "12.34", Currency: "USDT"}, + IntentRef: "intent-1", + OperationRef: "payment-1:hop_2_settlement_fx_convert", + PaymentRef: "payment-1", + } + receipt := &connectorv1.OperationReceipt{ + OperationId: "payment-1:hop_2_settlement_fx_convert", + ProviderRef: "provider-1", + Status: connectorv1.OperationStatus_OPERATION_WAITING, + } + + transfer := transferFromReceipt(req, receipt) + require.NotNil(t, transfer) + require.Equal(t, "payment-1:hop_2_settlement_fx_convert", transfer.GetTransferRef()) + require.Equal(t, "intent-1", transfer.GetIntentRef()) + require.Equal(t, "payment-1:hop_2_settlement_fx_convert", transfer.GetOperationRef()) + require.Equal(t, "payment-1", transfer.GetPaymentRef()) + require.Equal(t, chainv1.TransferStatus_TRANSFER_WAITING, transfer.GetStatus()) +} + +func TestSubmitTransfer_ForwardsOperationAndIntentReferences(t *testing.T) { + stub := &stubConnectorClient{ + submitResp: &connectorv1.SubmitOperationResponse{ + Receipt: &connectorv1.OperationReceipt{ + OperationId: "payment-1:hop_2_settlement_fx_convert", + Status: connectorv1.OperationStatus_OPERATION_WAITING, + ProviderRef: "provider-1", + }, + }, + } + client := NewWithClient(Config{}, stub) + + resp, err := client.SubmitTransfer(context.Background(), &chainv1.SubmitTransferRequest{ + IdempotencyKey: "idem-1", + OrganizationRef: "org-1", + SourceWalletRef: "wallet-src", + Destination: &chainv1.TransferDestination{ + Destination: &chainv1.TransferDestination_ManagedWalletRef{ + ManagedWalletRef: "wallet-dst", + }, + }, + Amount: &moneyv1.Money{Amount: "12.34", Currency: "USDT"}, + IntentRef: "intent-1", + OperationRef: "payment-1:hop_2_settlement_fx_convert", + PaymentRef: "payment-1", + }) + require.NoError(t, err) + require.NotNil(t, stub.submitReq) + require.NotNil(t, stub.submitReq.GetOperation()) + require.Equal(t, "intent-1", stub.submitReq.GetOperation().GetIntentRef()) + require.Equal(t, "payment-1:hop_2_settlement_fx_convert", stub.submitReq.GetOperation().GetOperationRef()) + require.NotNil(t, resp.GetTransfer()) + require.Equal(t, "payment-1:hop_2_settlement_fx_convert", resp.GetTransfer().GetTransferRef()) + require.Equal(t, "payment-1:hop_2_settlement_fx_convert", resp.GetTransfer().GetOperationRef()) + require.Equal(t, "intent-1", resp.GetTransfer().GetIntentRef()) +} + +func TestGetTransfer_UsesTransferRefAsOperationID(t *testing.T) { + stub := &stubConnectorClient{ + getResp: &connectorv1.GetOperationResponse{ + Operation: &connectorv1.Operation{ + OperationId: "transfer-1", + Status: connectorv1.OperationStatus_OPERATION_PROCESSING, + }, + }, + } + client := NewWithClient(Config{}, stub) + + resp, err := client.GetTransfer(context.Background(), &chainv1.GetTransferRequest{TransferRef: "transfer-1"}) + require.NoError(t, err) + require.NotNil(t, stub.getReq) + require.Equal(t, "transfer-1", stub.getReq.GetOperationId()) + require.NotNil(t, resp.GetTransfer()) + require.Equal(t, "transfer-1", resp.GetTransfer().GetTransferRef()) +} diff --git a/api/gateway/chain/go.mod b/api/gateway/chain/go.mod index 69e185ec..0597540d 100644 --- a/api/gateway/chain/go.mod +++ b/api/gateway/chain/go.mod @@ -16,7 +16,7 @@ require ( github.com/tech/sendico/pkg v0.1.0 go.mongodb.org/mongo-driver/v2 v2.5.0 go.uber.org/zap v1.27.1 - google.golang.org/grpc v1.79.1 + google.golang.org/grpc v1.79.2 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/api/gateway/chain/go.sum b/api/gateway/chain/go.sum index f91d85cf..0cf2f068 100644 --- a/api/gateway/chain/go.sum +++ b/api/gateway/chain/go.sum @@ -357,8 +357,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= -google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU= +google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/api/gateway/mntx/client/client_test.go b/api/gateway/mntx/client/client_test.go new file mode 100644 index 00000000..33c50c52 --- /dev/null +++ b/api/gateway/mntx/client/client_test.go @@ -0,0 +1,144 @@ +package client + +import ( + "context" + "testing" + + connectorv1 "github.com/tech/sendico/pkg/proto/connector/v1" + mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1" + "google.golang.org/grpc" +) + +type stubConnectorClient struct { + submitReq *connectorv1.SubmitOperationRequest + getReq *connectorv1.GetOperationRequest + + submitResp *connectorv1.SubmitOperationResponse + getResp *connectorv1.GetOperationResponse +} + +func (s *stubConnectorClient) SubmitOperation(_ context.Context, in *connectorv1.SubmitOperationRequest, _ ...grpc.CallOption) (*connectorv1.SubmitOperationResponse, error) { + s.submitReq = in + if s.submitResp != nil { + return s.submitResp, nil + } + return &connectorv1.SubmitOperationResponse{}, nil +} + +func (s *stubConnectorClient) GetOperation(_ context.Context, in *connectorv1.GetOperationRequest, _ ...grpc.CallOption) (*connectorv1.GetOperationResponse, error) { + s.getReq = in + if s.getResp != nil { + return s.getResp, nil + } + return &connectorv1.GetOperationResponse{}, nil +} + +func TestCreateCardPayout_UsesOperationRefIdentity(t *testing.T) { + stub := &stubConnectorClient{ + submitResp: &connectorv1.SubmitOperationResponse{ + Receipt: &connectorv1.OperationReceipt{ + OperationId: "payment-1:hop_4_card_payout_send", + Status: connectorv1.OperationStatus_OPERATION_WAITING, + ProviderRef: "provider-1", + }, + }, + } + client := &gatewayClient{client: stub, cfg: Config{}} + + resp, err := client.CreateCardPayout(context.Background(), &mntxv1.CardPayoutRequest{ + PayoutId: "payout-legacy-id", + OperationRef: "payment-1:hop_4_card_payout_send", + IdempotencyKey: "", + AmountMinor: 12345, + Currency: "RUB", + }) + if err != nil { + t.Fatalf("CreateCardPayout returned error: %v", err) + } + if resp.GetPayout() == nil { + t.Fatal("expected payout") + } + if got, want := resp.GetPayout().GetPayoutId(), "payment-1:hop_4_card_payout_send"; got != want { + t.Fatalf("payout_id mismatch: got=%q want=%q", got, want) + } + if stub.submitReq == nil || stub.submitReq.GetOperation() == nil { + t.Fatal("expected submitted operation") + } + if got, want := stub.submitReq.GetOperation().GetOperationRef(), "payment-1:hop_4_card_payout_send"; got != want { + t.Fatalf("operation_ref mismatch: got=%q want=%q", got, want) + } + if got, want := stub.submitReq.GetOperation().GetIdempotencyKey(), "payment-1:hop_4_card_payout_send"; got != want { + t.Fatalf("idempotency_key mismatch: got=%q want=%q", got, want) + } +} + +func TestGetCardPayoutStatus_UsesPayoutIDAsOperationID(t *testing.T) { + stub := &stubConnectorClient{ + getResp: &connectorv1.GetOperationResponse{ + Operation: &connectorv1.Operation{ + OperationId: "payment-2:hop_4_card_payout_send", + Status: connectorv1.OperationStatus_OPERATION_PROCESSING, + }, + }, + } + client := &gatewayClient{client: stub, cfg: Config{}} + + resp, err := client.GetCardPayoutStatus(context.Background(), &mntxv1.GetCardPayoutStatusRequest{ + PayoutId: "payment-2:hop_4_card_payout_send", + }) + if err != nil { + t.Fatalf("GetCardPayoutStatus returned error: %v", err) + } + if stub.getReq == nil { + t.Fatal("expected get operation request") + } + if got, want := stub.getReq.GetOperationId(), "payment-2:hop_4_card_payout_send"; got != want { + t.Fatalf("operation_id mismatch: got=%q want=%q", got, want) + } + if resp.GetPayout() == nil { + t.Fatal("expected payout") + } + if got, want := resp.GetPayout().GetPayoutId(), "payment-2:hop_4_card_payout_send"; got != want { + t.Fatalf("payout_id mismatch: got=%q want=%q", got, want) + } +} + +func TestCreateCardTokenPayout_UsesOperationRefWhenReceiptOperationIDMissing(t *testing.T) { + stub := &stubConnectorClient{ + submitResp: &connectorv1.SubmitOperationResponse{ + Receipt: &connectorv1.OperationReceipt{ + OperationId: "", + Status: connectorv1.OperationStatus_OPERATION_PROCESSING, + ProviderRef: "provider-2", + }, + }, + } + client := &gatewayClient{client: stub, cfg: Config{}} + + resp, err := client.CreateCardTokenPayout(context.Background(), &mntxv1.CardTokenPayoutRequest{ + PayoutId: "legacy-payout-id", + OperationRef: "payment-3:hop_4_card_payout_send_2", + IdempotencyKey: "", + AmountMinor: 777, + Currency: "RUB", + CardToken: "tok_123", + }) + if err != nil { + t.Fatalf("CreateCardTokenPayout returned error: %v", err) + } + if stub.submitReq == nil || stub.submitReq.GetOperation() == nil { + t.Fatal("expected submitted operation") + } + if got, want := stub.submitReq.GetOperation().GetOperationRef(), "payment-3:hop_4_card_payout_send_2"; got != want { + t.Fatalf("operation_ref mismatch: got=%q want=%q", got, want) + } + if got, want := stub.submitReq.GetOperation().GetIdempotencyKey(), "payment-3:hop_4_card_payout_send_2"; got != want { + t.Fatalf("idempotency_key mismatch: got=%q want=%q", got, want) + } + if resp.GetPayout() == nil { + t.Fatal("expected payout") + } + if got, want := resp.GetPayout().GetPayoutId(), "payment-3:hop_4_card_payout_send_2"; got != want { + t.Fatalf("payout_id mismatch: got=%q want=%q", got, want) + } +} diff --git a/api/gateway/mntx/go.mod b/api/gateway/mntx/go.mod index ac269ba6..a222477d 100644 --- a/api/gateway/mntx/go.mod +++ b/api/gateway/mntx/go.mod @@ -15,7 +15,7 @@ require ( github.com/tech/sendico/pkg v0.1.0 go.mongodb.org/mongo-driver/v2 v2.5.0 go.uber.org/zap v1.27.1 - google.golang.org/grpc v1.79.1 + google.golang.org/grpc v1.79.2 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/api/gateway/mntx/go.sum b/api/gateway/mntx/go.sum index bd4681c8..7f875b26 100644 --- a/api/gateway/mntx/go.sum +++ b/api/gateway/mntx/go.sum @@ -212,8 +212,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= -google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU= +google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/api/gateway/tron/client/client.go b/api/gateway/tron/client/client.go index 6131ace6..a72831d7 100644 --- a/api/gateway/tron/client/client.go +++ b/api/gateway/tron/client/client.go @@ -441,6 +441,8 @@ func operationFromTransfer(req *chainv1.SubmitTransferRequest) (*connectorv1.Ope From: &connectorv1.OperationParty{Ref: &connectorv1.OperationParty_Account{Account: &connectorv1.AccountRef{ConnectorId: chainConnectorID, AccountId: strings.TrimSpace(req.GetSourceWalletRef())}}}, Money: req.GetAmount(), Params: structFromMap(params), + IntentRef: strings.TrimSpace(req.GetIntentRef()), + OperationRef: strings.TrimSpace(req.GetOperationRef()), } to, err := destinationToParty(req.GetDestination()) if err != nil { @@ -490,6 +492,9 @@ func transferFromReceipt(req *chainv1.SubmitTransferRequest, receipt *connectorv transfer.Destination = req.GetDestination() transfer.RequestedAmount = req.GetAmount() transfer.NetAmount = req.GetAmount() + transfer.IntentRef = strings.TrimSpace(req.GetIntentRef()) + transfer.OperationRef = strings.TrimSpace(req.GetOperationRef()) + transfer.PaymentRef = strings.TrimSpace(req.GetPaymentRef()) } if receipt != nil { transfer.TransferRef = strings.TrimSpace(receipt.GetOperationId()) diff --git a/api/gateway/tron/client/client_test.go b/api/gateway/tron/client/client_test.go index f32d0d95..185fddd6 100644 --- a/api/gateway/tron/client/client_test.go +++ b/api/gateway/tron/client/client_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/require" + moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1" connectorv1 "github.com/tech/sendico/pkg/proto/connector/v1" chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1" "google.golang.org/grpc" @@ -13,6 +14,11 @@ import ( type stubConnectorClient struct { listReq *connectorv1.ListAccountsRequest + getReq *connectorv1.GetOperationRequest + + submitReq *connectorv1.SubmitOperationRequest + submitResp *connectorv1.SubmitOperationResponse + getResp *connectorv1.GetOperationResponse } func (s *stubConnectorClient) GetCapabilities(ctx context.Context, in *connectorv1.GetCapabilitiesRequest, opts ...grpc.CallOption) (*connectorv1.GetCapabilitiesResponse, error) { @@ -37,10 +43,18 @@ func (s *stubConnectorClient) GetBalance(ctx context.Context, in *connectorv1.Ge } func (s *stubConnectorClient) SubmitOperation(ctx context.Context, in *connectorv1.SubmitOperationRequest, opts ...grpc.CallOption) (*connectorv1.SubmitOperationResponse, error) { + s.submitReq = in + if s.submitResp != nil { + return s.submitResp, nil + } return &connectorv1.SubmitOperationResponse{}, nil } func (s *stubConnectorClient) GetOperation(ctx context.Context, in *connectorv1.GetOperationRequest, opts ...grpc.CallOption) (*connectorv1.GetOperationResponse, error) { + s.getReq = in + if s.getResp != nil { + return s.getResp, nil + } return &connectorv1.GetOperationResponse{}, nil } @@ -66,3 +80,84 @@ func TestListManagedWallets_ForwardsOrganizationRef(t *testing.T) { require.Equal(t, "owner-1", stub.listReq.GetOwnerRefFilter().GetValue()) require.Equal(t, connectorv1.AccountKind_CHAIN_MANAGED_WALLET, stub.listReq.GetKind()) } + +func TestTransferFromReceipt_PreservesRequestReferences(t *testing.T) { + req := &chainv1.SubmitTransferRequest{ + IdempotencyKey: "idem-1", + OrganizationRef: "org-1", + SourceWalletRef: "wallet-src", + Amount: &moneyv1.Money{Amount: "12.34", Currency: "USDT"}, + IntentRef: "intent-1", + OperationRef: "payment-1:hop_1_crypto_send", + PaymentRef: "payment-1", + } + receipt := &connectorv1.OperationReceipt{ + OperationId: "payment-1:hop_1_crypto_send", + ProviderRef: "provider-1", + Status: connectorv1.OperationStatus_OPERATION_WAITING, + } + + transfer := transferFromReceipt(req, receipt) + require.NotNil(t, transfer) + require.Equal(t, "payment-1:hop_1_crypto_send", transfer.GetTransferRef()) + require.Equal(t, "intent-1", transfer.GetIntentRef()) + require.Equal(t, "payment-1:hop_1_crypto_send", transfer.GetOperationRef()) + require.Equal(t, "payment-1", transfer.GetPaymentRef()) + require.Equal(t, chainv1.TransferStatus_TRANSFER_WAITING, transfer.GetStatus()) +} + +func TestSubmitTransfer_ForwardsOperationAndIntentReferences(t *testing.T) { + stub := &stubConnectorClient{ + submitResp: &connectorv1.SubmitOperationResponse{ + Receipt: &connectorv1.OperationReceipt{ + OperationId: "payment-1:hop_1_crypto_send", + Status: connectorv1.OperationStatus_OPERATION_WAITING, + ProviderRef: "provider-1", + }, + }, + } + client := NewWithClient(Config{}, stub) + + resp, err := client.SubmitTransfer(context.Background(), &chainv1.SubmitTransferRequest{ + IdempotencyKey: "idem-1", + OrganizationRef: "org-1", + SourceWalletRef: "wallet-src", + Destination: &chainv1.TransferDestination{ + Destination: &chainv1.TransferDestination_ManagedWalletRef{ + ManagedWalletRef: "wallet-dst", + }, + }, + Amount: &moneyv1.Money{Amount: "12.34", Currency: "USDT"}, + IntentRef: "intent-1", + OperationRef: "payment-1:hop_1_crypto_send", + PaymentRef: "payment-1", + }) + require.NoError(t, err) + require.NotNil(t, stub.submitReq) + require.NotNil(t, stub.submitReq.GetOperation()) + require.Equal(t, "intent-1", stub.submitReq.GetOperation().GetIntentRef()) + require.Equal(t, "payment-1:hop_1_crypto_send", stub.submitReq.GetOperation().GetOperationRef()) + require.NotNil(t, resp.GetTransfer()) + require.Equal(t, "payment-1:hop_1_crypto_send", resp.GetTransfer().GetTransferRef()) + require.Equal(t, "payment-1:hop_1_crypto_send", resp.GetTransfer().GetOperationRef()) + require.Equal(t, "intent-1", resp.GetTransfer().GetIntentRef()) +} + +func TestGetTransfer_UsesTransferRefAsOperationID(t *testing.T) { + stub := &stubConnectorClient{ + getResp: &connectorv1.GetOperationResponse{ + Operation: &connectorv1.Operation{ + OperationId: "transfer-1", + Status: connectorv1.OperationStatus_OPERATION_PROCESSING, + }, + }, + } + client := NewWithClient(Config{}, stub) + + resp, err := client.GetTransfer(context.Background(), &chainv1.GetTransferRequest{TransferRef: "transfer-1"}) + require.NoError(t, err) + require.NotNil(t, stub.getReq) + require.Equal(t, "transfer-1", stub.getReq.GetOperationId()) + require.NotNil(t, resp.GetTransfer()) + require.Equal(t, "transfer-1", resp.GetTransfer().GetTransferRef()) +} diff --git a/api/gateway/tron/go.mod b/api/gateway/tron/go.mod index f117a718..59f4c406 100644 --- a/api/gateway/tron/go.mod +++ b/api/gateway/tron/go.mod @@ -19,7 +19,7 @@ require ( github.com/tech/sendico/pkg v0.1.0 go.mongodb.org/mongo-driver/v2 v2.5.0 go.uber.org/zap v1.27.1 - google.golang.org/grpc v1.79.1 + google.golang.org/grpc v1.79.2 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/api/gateway/tron/go.sum b/api/gateway/tron/go.sum index 286e6285..9021bbf6 100644 --- a/api/gateway/tron/go.sum +++ b/api/gateway/tron/go.sum @@ -375,8 +375,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 h1: google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171/go.mod h1:M5krXqk4GhBKvB596udGL3UyjL4I1+cTbK0orROM9ng= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= -google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU= +google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=