From 7dd74799edeb396b8db117c0935c779129ef1715 Mon Sep 17 00:00:00 2001 From: connorwstein Date: Thu, 15 Jan 2026 10:50:29 -0500 Subject: [PATCH] Prefix helper --- keystore/keystore.go | 16 +++++++++++++- keystore/keystore_internal_test.go | 34 ++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/keystore/keystore.go b/keystore/keystore.go index 15306cda22..dce33c613f 100644 --- a/keystore/keystore.go +++ b/keystore/keystore.go @@ -35,6 +35,20 @@ func (k KeyPath) Base() string { return k[len(k)-1] } +// HasPrefix returns true if k starts with the given prefix path. +// For example, KeyPath{"solana", "tx", "my-key"}.HasPrefix(KeyPath{"solana", "tx"}) returns true. +func (k KeyPath) HasPrefix(prefix KeyPath) bool { + if len(prefix) > len(k) { + return false + } + for i := range prefix { + if k[i] != prefix[i] { + return false + } + } + return true +} + func NewKeyPath(segments ...string) KeyPath { return segments } @@ -44,7 +58,7 @@ func NewKeyPathFromString(fullName string) KeyPath { } // joinKeySegments joins path-like key name segments using "/" and avoids double slashes. -// Empty segments are skipped so joinKeySegments("EVM", "TX", "my-key") => "EVM/TX/my-key". +// Empty segments are skipped so joinKeySegments("evm", "tx", "my-key") => "evm/tx/my-key". func joinKeySegments(segments ...string) string { cleaned := make([]string, 0, len(segments)) for _, s := range segments { diff --git a/keystore/keystore_internal_test.go b/keystore/keystore_internal_test.go index 515a3987a8..4418dd9b62 100644 --- a/keystore/keystore_internal_test.go +++ b/keystore/keystore_internal_test.go @@ -36,17 +36,33 @@ func TestJoinKeySegments(t *testing.T) { segments []string expected string }{ - {segments: []string{"EVM", "TX", "my-key"}, expected: "EVM/TX/my-key"}, - {segments: []string{"EVM", "/TX", "my-key"}, expected: "EVM/TX/my-key"}, - {segments: []string{"EVM", "TX/", "my-key"}, expected: "EVM/TX/my-key"}, - {segments: []string{"EVM", "TX", "/my-key"}, expected: "EVM/TX/my-key"}, - {segments: []string{"EVM", "TX", "my-key", ""}, expected: "EVM/TX/my-key"}, - {segments: []string{"EVM", "TX", "my-key", "/"}, expected: "EVM/TX/my-key"}, - {segments: []string{"EVM", "TX", "my-key", "//"}, expected: "EVM/TX/my-key"}, - {segments: []string{"EVM", "TX", "my-key", "///"}, expected: "EVM/TX/my-key"}, - {segments: []string{"EVM", "TX", "my-key", "////"}, expected: "EVM/TX/my-key"}, + {segments: []string{"evm", "tx", "my-key"}, expected: "evm/tx/my-key"}, + {segments: []string{"evm", "/tx", "my-key"}, expected: "evm/tx/my-key"}, + {segments: []string{"evm", "tx/", "my-key"}, expected: "evm/tx/my-key"}, + {segments: []string{"evm", "tx", "/my-key"}, expected: "evm/tx/my-key"}, + {segments: []string{"evm", "tx", "my-key", ""}, expected: "evm/tx/my-key"}, + {segments: []string{"evm", "tx", "my-key", "/"}, expected: "evm/tx/my-key"}, + {segments: []string{"evm", "tx", "my-key", "//"}, expected: "evm/tx/my-key"}, + {segments: []string{"evm", "tx", "my-key", "///"}, expected: "evm/tx/my-key"}, + {segments: []string{"evm", "tx", "my-key", "////"}, expected: "evm/tx/my-key"}, } for _, tt := range tests { require.Equal(t, tt.expected, joinKeySegments(tt.segments...)) } } + +func TestKeyPathHasPrefix(t *testing.T) { + tests := []struct { + path KeyPath + prefix KeyPath + expected bool + }{ + {path: KeyPath{"evm", "tx", "my-key"}, prefix: KeyPath{"evm", "tx"}, expected: true}, + {path: KeyPath{"evm", "tx", "my-key"}, prefix: KeyPath{"evm"}, expected: true}, + {path: KeyPath{"evm", "tx", "my-key"}, prefix: KeyPath{"evm", "tx", "my-key"}, expected: true}, + {path: KeyPath{"evm", "tx", "my-key"}, prefix: KeyPath{"evm", "tx", "my-key", "extra"}, expected: false}, + } + for _, tt := range tests { + require.Equal(t, tt.expected, tt.path.HasPrefix(tt.prefix)) + } +}