@@ -6,8 +6,13 @@ import (
66
77 "cosmossdk.io/errors"
88 "cosmossdk.io/store/prefix"
9+ storetypes "cosmossdk.io/store/types"
10+ "github.com/cosmos/cosmos-sdk/telemetry"
911 sdk "github.com/cosmos/cosmos-sdk/types"
12+ sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
1013 gogotypes "github.com/cosmos/gogoproto/types"
14+ "github.com/dydxprotocol/v4-chain/protocol/lib/metrics"
15+ "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/authenticator"
1116 "github.com/dydxprotocol/v4-chain/protocol/x/accountplus/types"
1217)
1318
@@ -106,3 +111,124 @@ func (k Keeper) SetNextAuthenticatorId(ctx sdk.Context, authenticatorId uint64)
106111 store := ctx .KVStore (k .storeKey )
107112 store .Set ([]byte (types .AuthenticatorIdKeyPrefix ), b )
108113}
114+
115+ // GetSelectedAuthenticatorData gets a single authenticator for the account from the store.
116+ func (k Keeper ) GetSelectedAuthenticatorData (
117+ ctx sdk.Context ,
118+ account sdk.AccAddress ,
119+ selectedAuthenticator uint64 ,
120+ ) (* types.AccountAuthenticator , error ) {
121+ store := prefix .NewStore (
122+ ctx .KVStore (k .storeKey ),
123+ []byte (types .AuthenticatorKeyPrefix ),
124+ )
125+ bz := store .Get (types .KeyAccountId (account , selectedAuthenticator ))
126+ if bz == nil {
127+ return & types.AccountAuthenticator {}, errors .Wrap (
128+ types .ErrAuthenticatorNotFound ,
129+ fmt .Sprintf ("authenticator %d not found for account %s" , selectedAuthenticator , account ),
130+ )
131+ }
132+ authenticatorFromStore , err := k .unmarshalAccountAuthenticator (bz )
133+ if err != nil {
134+ return & types.AccountAuthenticator {}, err
135+ }
136+
137+ return authenticatorFromStore , nil
138+ }
139+
140+ // GetInitializedAuthenticatorForAccount returns a single initialized authenticator for the account.
141+ // It fetches the authenticator data from the store, gets the authenticator struct from the manager,
142+ // then calls initialize on the authenticator data
143+ func (k Keeper ) GetInitializedAuthenticatorForAccount (
144+ ctx sdk.Context ,
145+ account sdk.AccAddress ,
146+ selectedAuthenticator uint64 ,
147+ ) (authenticator.InitializedAuthenticator , error ) {
148+ // Get the authenticator data from the store
149+ authenticatorFromStore , err := k .GetSelectedAuthenticatorData (ctx , account , selectedAuthenticator )
150+ if err != nil {
151+ return authenticator.InitializedAuthenticator {}, err
152+ }
153+
154+ uninitializedAuthenticator := k .authenticatorManager .GetAuthenticatorByType (authenticatorFromStore .Type )
155+ if uninitializedAuthenticator == nil {
156+ // This should never happen, but if it does, it means that stored authenticator is not registered
157+ // or somehow the registered authenticator was removed / malformed
158+ telemetry .IncrCounter (1 , metrics .MissingRegisteredAuthenticator )
159+ k .Logger (ctx ).Error (
160+ "account asscoicated authenticator not registered in manager" ,
161+ "type" , authenticatorFromStore .Type ,
162+ "id" , selectedAuthenticator ,
163+ )
164+
165+ return authenticator.InitializedAuthenticator {},
166+ errors .Wrapf (
167+ sdkerrors .ErrLogic ,
168+ "authenticator id %d failed to initialize, authenticator type %s not registered in manager" ,
169+ selectedAuthenticator , authenticatorFromStore .Type ,
170+ )
171+ }
172+ // Ensure that initialization of each authenticator works as expected
173+ // NOTE: Always return a concrete authenticator not a pointer, do not modify in place
174+ // NOTE: The authenticator manager returns a struct that is reused
175+ initializedAuthenticator , err := uninitializedAuthenticator .Initialize (authenticatorFromStore .Config )
176+ if err != nil {
177+ return authenticator.InitializedAuthenticator {},
178+ errors .Wrapf (
179+ err ,
180+ "authenticator %d with type %s failed to initialize" ,
181+ selectedAuthenticator , authenticatorFromStore .Type ,
182+ )
183+ }
184+ if initializedAuthenticator == nil {
185+ return authenticator.InitializedAuthenticator {},
186+ errors .Wrapf (
187+ types .ErrInitializingAuthenticator ,
188+ "authenticator.Initialize returned nil for %d with type %s" ,
189+ selectedAuthenticator , authenticatorFromStore .Type ,
190+ )
191+ }
192+
193+ finalAuthenticator := authenticator.InitializedAuthenticator {
194+ Id : authenticatorFromStore .Id ,
195+ Authenticator : initializedAuthenticator ,
196+ }
197+
198+ return finalAuthenticator , nil
199+ }
200+
201+ // GetAuthenticatorDataForAccount gets all authenticators AccAddressFromBech32 with an account
202+ // from the store.
203+ func (k Keeper ) GetAuthenticatorDataForAccount (
204+ ctx sdk.Context ,
205+ account sdk.AccAddress ,
206+ ) ([]* types.AccountAuthenticator , error ) {
207+ authenticators := make ([]* types.AccountAuthenticator , 0 )
208+
209+ store := prefix .NewStore (
210+ ctx .KVStore (k .storeKey ),
211+ []byte (types .AuthenticatorKeyPrefix ),
212+ )
213+ iterator := storetypes .KVStorePrefixIterator (store , []byte (account .String ()))
214+ defer iterator .Close ()
215+ for ; iterator .Valid (); iterator .Next () {
216+ authenticator , err := k .unmarshalAccountAuthenticator (iterator .Value ())
217+ if err != nil {
218+ return nil , err
219+ }
220+ authenticators = append (authenticators , authenticator )
221+ }
222+
223+ return authenticators , nil
224+ }
225+
226+ // unmarshalAccountAuthenticator is used to unmarshal the AccountAuthenticator from the store
227+ func (k Keeper ) unmarshalAccountAuthenticator (bz []byte ) (* types.AccountAuthenticator , error ) {
228+ var accountAuthenticator types.AccountAuthenticator
229+ err := k .cdc .Unmarshal (bz , & accountAuthenticator )
230+ if err != nil {
231+ return & types.AccountAuthenticator {}, errors .Wrap (err , "failed to unmarshal account authenticator" )
232+ }
233+ return & accountAuthenticator , nil
234+ }
0 commit comments