From 62c2f0fbdc2e502c9a3c66807c802b0b275994fb Mon Sep 17 00:00:00 2001 From: rawdaGastan Date: Sun, 21 Dec 2025 17:07:44 +0200 Subject: [PATCH] add stash account functions --- clients/tfchain-client-go/twin.go | 54 ++++++++++++++++++++++++++ clients/tfchain-client-go/twin_test.go | 34 ++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/clients/tfchain-client-go/twin.go b/clients/tfchain-client-go/twin.go index c4600e3b3..ff1bb398e 100644 --- a/clients/tfchain-client-go/twin.go +++ b/clients/tfchain-client-go/twin.go @@ -182,3 +182,57 @@ func (s *Substrate) UpdateTwin(identity Identity, relay string, pk []byte) (uint return s.GetTwinByPubKey(identity.PublicKey()) } + +// BondTwinAccount bonds a twin with a stash/savings account +// The stash account should initiate the bond between the twin and the account address +func (s *Substrate) BondTwinAccount(identity Identity, twinID uint32) error { + cl, meta, err := s.GetClient() + if err != nil { + return err + } + + c, err := types.NewCall(meta, "TfgridModule.bond_twin_account", twinID) + if err != nil { + return errors.Wrap(err, "failed to create call") + } + + if _, err := s.Call(cl, meta, identity, c); err != nil { + return errors.Wrap(err, "failed to bond twin account") + } + + return nil +} + +// GetTwinBondedAccount gets the bonded/stash account for a twin +func (s *Substrate) GetTwinBondedAccount(twinID uint32) (*AccountID, error) { + cl, meta, err := s.GetClient() + if err != nil { + return nil, err + } + + bytes, err := Encode(twinID) + if err != nil { + return nil, errors.Wrap(err, "substrate: encoding error building query arguments") + } + + key, err := types.CreateStorageKey(meta, "TfgridModule", "TwinBoundedAccountID", bytes, nil) + if err != nil { + return nil, errors.Wrap(err, "failed to create substrate query key") + } + + raw, err := cl.RPC.State.GetStorageRawLatest(key) + if err != nil { + return nil, errors.Wrap(err, "failed to lookup twin bonded account") + } + + if len(*raw) == 0 { + return nil, nil // No bonded account found + } + + var accountID AccountID + if err := Decode(*raw, &accountID); err != nil { + return nil, errors.Wrap(err, "failed to decode account") + } + + return &accountID, nil +} diff --git a/clients/tfchain-client-go/twin_test.go b/clients/tfchain-client-go/twin_test.go index d4d10f1ae..61d4636ba 100644 --- a/clients/tfchain-client-go/twin_test.go +++ b/clients/tfchain-client-go/twin_test.go @@ -23,3 +23,37 @@ func TestTwin(t *testing.T) { require.Equal(t, uint32(twin.ID), id) } + +func TestBondTwinAccount(t *testing.T) { + cl := startLocalConnection(t) + defer cl.Close() + + twinID := assertCreateTwin(t, cl, AccountBob) + + // Get Alice Stash identity to act as the bonded account + stashUser := Accounts[AccountAliceStash] + stashIdentity, err := NewIdentityFromSr25519Phrase(stashUser.Phrase) + require.NoError(t, err) + + err = cl.BondTwinAccount(stashIdentity, twinID) + require.NoError(t, err) + + bondedAccount, err := cl.GetTwinBondedAccount(twinID) + require.NoError(t, err) + require.NotNil(t, bondedAccount) + + stashAccount, err := FromAddress(stashUser.Address) + require.NoError(t, err) + require.Equal(t, stashAccount.PublicKey(), bondedAccount.PublicKey()) +} + +func TestGetTwinBondedAccount_NotBonded(t *testing.T) { + cl := startLocalConnection(t) + defer cl.Close() + + twinID := assertCreateTwin(t, cl, AccountAlice) + + bondedAccount, err := cl.GetTwinBondedAccount(twinID) + require.NoError(t, err) + require.Nil(t, bondedAccount) +}