From 39b1e37b9ebad4095c35d86e5664b62fe751f246 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 8 Jan 2026 21:23:43 +0000 Subject: [PATCH 1/2] Initial plan From dbecff58db71c338931d56ea4e4ae98d81985d65 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 8 Jan 2026 21:29:08 +0000 Subject: [PATCH 2/2] fix(init): preserve protocol selection order from server Add protocolOrder slice to track insertion order when grouping generators by protocol, ensuring the protocol selection menu displays options in the order the server intended (sorted by weight). Co-authored-by: maoueh <123014+maoueh@users.noreply.github.com> --- cmd/substreams/init.go | 6 +++- cmd/substreams/init_test.go | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 cmd/substreams/init_test.go diff --git a/cmd/substreams/init.go b/cmd/substreams/init.go index 28a9bfba6..e43851048 100644 --- a/cmd/substreams/init.go +++ b/cmd/substreams/init.go @@ -208,12 +208,15 @@ func runSubstreamsInitE(cmd *cobra.Command, args []string) error { Generators []*pbconvo.DiscoveryResponse_Generator } + // Use a slice to maintain insertion order and a map for lookup + var protocolOrder []string filteredProtocols := make(map[string]*BlockchainProtocolSelector) for _, gen := range resp.Msg.Generators { selector, groupExists := filteredProtocols[gen.Group] if groupExists { selector.Generators = append(selector.Generators, gen) } else { + protocolOrder = append(protocolOrder, gen.Group) filteredProtocols[gen.Group] = &BlockchainProtocolSelector{ Id: gen.Group, Title: gen.Group, @@ -223,7 +226,8 @@ func runSubstreamsInitE(cmd *cobra.Command, args []string) error { } protocolOptions := make([]huh.Option[*BlockchainProtocolSelector], 0, len(filteredProtocols)) - for _, value := range filteredProtocols { + for _, group := range protocolOrder { + value := filteredProtocols[group] protocolOptions = append(protocolOptions, huh.Option[*BlockchainProtocolSelector]{ Key: value.Title, Value: value, diff --git a/cmd/substreams/init_test.go b/cmd/substreams/init_test.go new file mode 100644 index 000000000..e29ed19a7 --- /dev/null +++ b/cmd/substreams/init_test.go @@ -0,0 +1,60 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + pbconvo "github.com/streamingfast/substreams/pb/sf/codegen/conversation/v1" +) + +func TestProtocolOrderPreservation(t *testing.T) { + // Simulate generators received from server in specific order + generators := []*pbconvo.DiscoveryResponse_Generator{ + {Id: "evm-events-calls", Group: "EVM", Title: "EVM Events/Calls"}, + {Id: "evm-hello-world", Group: "EVM", Title: "EVM Hello World"}, + {Id: "sol-anchor", Group: "Solana", Title: "Solana Anchor"}, + {Id: "sol-hello-world", Group: "Solana", Title: "Solana Hello World"}, + {Id: "starknet-events", Group: "Starknet", Title: "Starknet Events"}, + } + + // Reproduce the grouping logic + type BlockchainProtocolSelector struct { + Id string + Title string + Generators []*pbconvo.DiscoveryResponse_Generator + } + + var protocolOrder []string + filteredProtocols := make(map[string]*BlockchainProtocolSelector) + for _, gen := range generators { + selector, groupExists := filteredProtocols[gen.Group] + if groupExists { + selector.Generators = append(selector.Generators, gen) + } else { + protocolOrder = append(protocolOrder, gen.Group) + filteredProtocols[gen.Group] = &BlockchainProtocolSelector{ + Id: gen.Group, + Title: gen.Group, + Generators: []*pbconvo.DiscoveryResponse_Generator{gen}, + } + } + } + + // Verify order is preserved + require.Len(t, protocolOrder, 3) + assert.Equal(t, "EVM", protocolOrder[0]) + assert.Equal(t, "Solana", protocolOrder[1]) + assert.Equal(t, "Starknet", protocolOrder[2]) + + // Verify generators within each group maintain order + evmGens := filteredProtocols["EVM"].Generators + require.Len(t, evmGens, 2) + assert.Equal(t, "evm-events-calls", evmGens[0].Id) + assert.Equal(t, "evm-hello-world", evmGens[1].Id) + + solanaGens := filteredProtocols["Solana"].Generators + require.Len(t, solanaGens, 2) + assert.Equal(t, "sol-anchor", solanaGens[0].Id) + assert.Equal(t, "sol-hello-world", solanaGens[1].Id) +}