Skip to content

feat: Add persistent shard and realm support to Client #1395

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 25, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
62 changes: 46 additions & 16 deletions sdk/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
operator *_Operator

network _Network
shard uint64
realm uint64
mirrorNetwork *_MirrorNetwork
autoValidateChecksums bool
defaultRegenerateTransactionIDs bool
Expand Down Expand Up @@ -71,7 +73,7 @@
// ClientForMirrorNetworkWithRealmAndShard constructs a client given a set of mirror network nodes and the realm/shard of the address book.
func ClientForMirrorNetworkWithRealmAndShard(mirrorNetwork []string, realm uint64, shard uint64) (*Client, error) {
net := _NewNetwork()
client := _NewClient(net, mirrorNetwork, nil, true)
client := _NewClient(net, mirrorNetwork, nil, true, realm, shard)
addressbook, err := NewAddressBookQuery().
SetFileID(GetAddressBookFileIDFor(realm, shard)).
Execute(client)
Expand All @@ -85,7 +87,15 @@
// ClientForNetwork constructs a client given a set of nodes.
func ClientForNetwork(network map[string]AccountID) *Client {
net := _NewNetwork()
client := _NewClient(net, []string{}, nil, true)
client := _NewClient(net, []string{}, nil, true, 0, 0)
_ = client.SetNetwork(network)
return client
}

// ClientForNetwork constructs a client given a set of nodes.
func ClientForNetworkShardRealm(network map[string]AccountID, shard uint64, realm uint64) *Client {
net := _NewNetwork()
client := _NewClient(net, []string{}, nil, true, shard, realm)

Check warning on line 98 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L96-L98

Added lines #L96 - L98 were not covered by tests
_ = client.SetNetwork(network)
return client
}
Expand All @@ -95,28 +105,40 @@
// Most users will want to set an _Operator account with .SetOperator so
// transactions can be automatically given TransactionIDs and signed.
func ClientForMainnet() *Client {
return _NewClient(*_NetworkForMainnet(mainnetNodes._ToMap()), mainnetMirror, NewLedgerIDMainnet(), true)
return _NewClient(*_NetworkForMainnet(mainnetNodes._ToMap()), mainnetMirror, NewLedgerIDMainnet(), true, 0, 0)
}

func ClientForMainnetShardRealm(shard uint64, realm uint64) *Client {
return _NewClient(*_NetworkForMainnet(mainnetNodes._ToMap()), mainnetMirror, NewLedgerIDMainnet(), true, shard, realm)

Check warning on line 112 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L111-L112

Added lines #L111 - L112 were not covered by tests
}

// ClientForTestnet returns a preconfigured client for use with the standard
// Hiero testnet.
// Most users will want to set an _Operator account with .SetOperator so
// transactions can be automatically given TransactionIDs and signed.
func ClientForTestnet() *Client {
return _NewClient(*_NetworkForTestnet(testnetNodes._ToMap()), testnetMirror, NewLedgerIDTestnet(), true)
return _NewClient(*_NetworkForTestnet(testnetNodes._ToMap()), testnetMirror, NewLedgerIDTestnet(), true, 0, 0)
}

func ClientForTestnetShardRealm(shard uint64, realm uint64) *Client {
return _NewClient(*_NetworkForTestnet(testnetNodes._ToMap()), testnetMirror, NewLedgerIDTestnet(), true, shard, realm)

Check warning on line 124 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L123-L124

Added lines #L123 - L124 were not covered by tests
}

// ClientForPreviewnet returns a preconfigured client for use with the standard
// Hiero previewnet.
// Most users will want to set an _Operator account with .SetOperator so
// transactions can be automatically given TransactionIDs and signed.
func ClientForPreviewnet() *Client {
return _NewClient(*_NetworkForPreviewnet(previewnetNodes._ToMap()), previewnetMirror, NewLedgerIDPreviewnet(), true)
return _NewClient(*_NetworkForPreviewnet(previewnetNodes._ToMap()), previewnetMirror, NewLedgerIDPreviewnet(), true, 0, 0)

Check warning on line 132 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L132

Added line #L132 was not covered by tests
}

func ClientForPreviewnetShardRealm(shard uint64, realm uint64) *Client {
return _NewClient(*_NetworkForPreviewnet(previewnetNodes._ToMap()), previewnetMirror, NewLedgerIDPreviewnet(), true, shard, realm)

Check warning on line 136 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L135-L136

Added lines #L135 - L136 were not covered by tests
}

// newClient takes in a map of _Node addresses to their respective IDS (_Network)
// and returns a Client instance which can be used to
func _NewClient(network _Network, mirrorNetwork []string, ledgerId *LedgerID, shouldScheduleNetworkUpdate bool) *Client {
func _NewClient(network _Network, mirrorNetwork []string, ledgerId *LedgerID, shouldScheduleNetworkUpdate bool, shard uint64, realm uint64) *Client {
ctx, cancel := context.WithCancel(context.Background())
logger := NewLogger("hiero-sdk-go", LogLevel(os.Getenv("HEDERA_SDK_GO_LOG_LEVEL")))
var defaultLogger Logger = logger
Expand All @@ -134,6 +156,8 @@
networkUpdateContext: ctx,
cancelNetworkUpdate: cancel,
logger: defaultLogger,
shard: shard,
realm: realm,
}

client.SetMirrorNetwork(mirrorNetwork)
Expand All @@ -153,7 +177,7 @@

func (client *Client) _UpdateAddressBook() {
addressbook, err := NewAddressBookQuery().
SetFileID(FileIDForAddressBook()).
SetFileID(GetAddressBookFileIDFor(client.shard, client.realm)).
Execute(client)
if err == nil && len(addressbook.NodeAddresses) > 0 {
client.SetNetworkFromAddressBook(addressbook)
Expand Down Expand Up @@ -192,18 +216,22 @@

// ClientForName set up the client for the selected network.
func ClientForName(name string) (*Client, error) {
return ClientForNameShardRealm(name, 0, 0)

Check warning on line 219 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L219

Added line #L219 was not covered by tests
}

func ClientForNameShardRealm(name string, shard uint64, realm uint64) (*Client, error) {

Check warning on line 222 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L222

Added line #L222 was not covered by tests
switch name {
case string(NetworkNameTestnet):
return ClientForTestnet(), nil
return ClientForTestnetShardRealm(shard, realm), nil

Check warning on line 225 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L225

Added line #L225 was not covered by tests
case string(NetworkNamePreviewnet):
return ClientForPreviewnet(), nil
return ClientForPreviewnetShardRealm(shard, realm), nil

Check warning on line 227 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L227

Added line #L227 was not covered by tests
case string(NetworkNameMainnet):
return ClientForMainnet(), nil
return ClientForMainnetShardRealm(shard, realm), nil

Check warning on line 229 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L229

Added line #L229 was not covered by tests
case "local", "localhost":
network := make(map[string]AccountID)
network["127.0.0.1:50213"] = AccountID{Account: 3}
mirror := []string{"127.0.0.1:5600"}
client := ClientForNetwork(network)
client := ClientForNetworkShardRealm(network, shard, realm)

Check warning on line 234 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L234

Added line #L234 was not covered by tests
client.SetMirrorNetwork(mirror)
return client, nil
default:
Expand All @@ -219,6 +247,8 @@
// TODO: Implement complete spec: https://gitlab.com/launchbadge/hedera/sdk/python/-/issues/45
type _ClientConfig struct {
Network interface{} `json:"network"`
Shard uint64 `json:"shard"`
Realm uint64 `json:"realm"`
MirrorNetwork interface{} `json:"mirrorNetwork"`
Operator *_ConfigOperator `json:"operator"`
}
Expand Down Expand Up @@ -293,20 +323,20 @@
return client, errors.New("mirrorNetwork is expected to be either string or an array of strings")
}
}
client = _NewClient(network, arr, nil, shouldScheduleNetworkUpdate)
client = _NewClient(network, arr, nil, shouldScheduleNetworkUpdate, clientConfig.Shard, clientConfig.Realm)
case string:
if len(mirror) > 0 {
switch mirror {
case string(NetworkNameMainnet):
client = _NewClient(network, mainnetMirror, NewLedgerIDMainnet(), shouldScheduleNetworkUpdate)
client = _NewClient(network, mainnetMirror, NewLedgerIDMainnet(), shouldScheduleNetworkUpdate, clientConfig.Shard, clientConfig.Realm)

Check warning on line 331 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L331

Added line #L331 was not covered by tests
case string(NetworkNameTestnet):
client = _NewClient(network, testnetMirror, NewLedgerIDTestnet(), shouldScheduleNetworkUpdate)
client = _NewClient(network, testnetMirror, NewLedgerIDTestnet(), shouldScheduleNetworkUpdate, clientConfig.Shard, clientConfig.Realm)
case string(NetworkNamePreviewnet):
client = _NewClient(network, previewnetMirror, NewLedgerIDPreviewnet(), shouldScheduleNetworkUpdate)
client = _NewClient(network, previewnetMirror, NewLedgerIDPreviewnet(), shouldScheduleNetworkUpdate, clientConfig.Shard, clientConfig.Realm)

Check warning on line 335 in sdk/client.go

View check run for this annotation

Codecov / codecov/patch

sdk/client.go#L335

Added line #L335 was not covered by tests
}
}
case nil:
client = _NewClient(network, []string{}, nil, true)
client = _NewClient(network, []string{}, nil, true, clientConfig.Shard, clientConfig.Realm)
default:
return client, errors.New("mirrorNetwork is expected to be a string, an array of strings or nil")
}
Expand Down
2 changes: 1 addition & 1 deletion sdk/client_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func DisabledTestIntegrationClientPingAllBadNetwork(t *testing.T) { // nolint
netwrk := _NewNetwork()
netwrk.SetNetwork(env.Client.GetNetwork())

tempClient := _NewClient(netwrk, env.Client.GetMirrorNetwork(), env.Client.GetLedgerID(), true)
tempClient := _NewClient(netwrk, env.Client.GetMirrorNetwork(), env.Client.GetLedgerID(), true, 0, 0)
tempClient.SetOperator(env.OperatorID, env.OperatorKey)

tempClient.SetMaxNodeAttempts(1)
Expand Down
2 changes: 2 additions & 0 deletions sdk/utilities_for_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ var testTransactionID TransactionID = TransactionID{
}

const testClientJSON string = `{
"shard": 0,
"realm": 0,
"network": {
"35.237.200.180:50211": "0.0.3",
"35.186.191.247:50211": "0.0.4",
Expand Down
Loading