@@ -14,6 +14,13 @@ export type AccountType = string;
1414export type AccountMethod = string ;
1515
1616export type AccountProvider = {
17+ getEntropySources : ( ) => EntropySourceId [ ] ;
18+
19+ getAccounts : ( opts : {
20+ entropySource : EntropySourceId ;
21+ groupIndex : number ;
22+ } ) => InternalAccount [ ] ;
23+
1724 createAccounts : ( opts : {
1825 entropySource : EntropySourceId ;
1926 groupIndex : number ;
@@ -39,7 +46,7 @@ export type MultichainAccountSelector = {
3946
4047export type MultichainAccount = {
4148 get id ( ) : MultichainAccountId ;
42- get walletId ( ) : MultichainAccountWalletId ;
49+ get wallet ( ) : MultichainAccountWallet ;
4350 get index ( ) : number ;
4451 get accounts ( ) : InternalAccount [ ] ;
4552
@@ -98,33 +105,63 @@ export function toMultichainAccountId(
98105export class MultichainAccountAdapter implements MultichainAccount {
99106 readonly #id: MultichainAccountId ;
100107
101- readonly #walletId: MultichainAccountWalletId ;
108+ readonly #wallet: MultichainAccountWallet ;
102109
103110 readonly #index: number ;
104111
105- readonly #accounts: InternalAccount [ ] ;
112+ readonly #providers: AccountProvider [ ] ;
113+
114+ #accounts: InternalAccount [ ] ;
106115
107116 constructor ( {
108- accounts,
109117 groupIndex,
110- walletId,
118+ wallet,
119+ providers,
111120 } : {
112- accounts : InternalAccount [ ] ;
113121 groupIndex : number ;
114- walletId : MultichainAccountWalletId ;
122+ wallet : MultichainAccountWallet ;
123+ providers : AccountProvider [ ] ;
115124 } ) {
116- this . #id = toMultichainAccountId ( walletId , groupIndex ) ;
125+ this . #id = toMultichainAccountId ( wallet . id , groupIndex ) ;
117126 this . #index = groupIndex ;
127+ this . #wallet = wallet ;
128+ this . #providers = providers ;
129+ this . #accounts = [ ] ;
130+ }
131+
132+ async init ( ) : Promise < void > {
133+ let accounts : InternalAccount [ ] = [ ] ;
134+
135+ for ( const provider of this . #providers) {
136+ accounts = accounts . concat (
137+ provider . getAccounts ( {
138+ entropySource : this . #wallet. entropySource ,
139+ groupIndex : this . #index,
140+ } ) ,
141+ ) ;
142+ }
143+
118144 this . #accounts = accounts ;
119- this . #walletId = walletId ;
145+ }
146+
147+ static async from ( args : {
148+ groupIndex : number ;
149+ wallet : MultichainAccountWallet ;
150+ providers : AccountProvider [ ] ;
151+ } ) : Promise < MultichainAccount > {
152+ const multichainAccount = new MultichainAccountAdapter ( args ) ;
153+
154+ await multichainAccount . init ( ) ;
155+
156+ return multichainAccount ;
120157 }
121158
122159 get id ( ) : MultichainAccountId {
123160 return this . #id;
124161 }
125162
126- get walletId ( ) : MultichainAccountWalletId {
127- return this . #walletId ;
163+ get wallet ( ) : MultichainAccountWallet {
164+ return this . #wallet ;
128165 }
129166
130167 get index ( ) : number {
@@ -225,22 +262,47 @@ export class MultichainAccountWalletAdapter implements MultichainAccountWallet {
225262 constructor ( {
226263 providers,
227264 entropySource,
228- multichainAccounts,
229265 } : {
230266 providers : AccountProvider [ ] ;
231267 entropySource : EntropySourceId ;
232- multichainAccounts : { [ groupIndex : number ] : MultichainAccount } ;
233268 } ) {
234269 this . #id = toMultichainAccountWalletId ( entropySource ) ;
235270 this . #providers = providers ;
236271 this . #entropySource = entropySource ;
237272
238273 this . #accounts = new Map ( ) ;
239- for ( const [ groupIndex , multichainAccount ] of Object . entries (
240- multichainAccounts ,
241- ) ) {
242- this . #accounts. set ( groupIndex as unknown as number , multichainAccount ) ;
243- }
274+ }
275+
276+ async init ( ) : Promise < void > {
277+ let index = 0 ;
278+ let hasAccounts = false ;
279+
280+ do {
281+ // Make an explicit const copy of that value, to avoid unsafe reference.
282+ // See: https://eslint.org/docs/latest/rules/no-loop-func
283+ const groupIndex = index ;
284+
285+ hasAccounts = this . #providers. some ( ( provider ) => {
286+ return Boolean (
287+ provider . getAccounts ( {
288+ entropySource : this . #entropySource,
289+ groupIndex,
290+ } ) . length ,
291+ ) ;
292+ } ) ;
293+
294+ if ( hasAccounts ) {
295+ const multichainAccount = await MultichainAccountAdapter . from ( {
296+ groupIndex,
297+ wallet : this ,
298+ providers : this . #providers,
299+ } ) ;
300+
301+ this . #accounts. set ( groupIndex , multichainAccount ) ;
302+ }
303+
304+ index += 1 ;
305+ } while ( hasAccounts ) ;
244306 }
245307
246308 get id ( ) : MultichainAccountWalletId {
@@ -255,14 +317,13 @@ export class MultichainAccountWalletAdapter implements MultichainAccountWallet {
255317 return Array . from ( this . #accounts. values ( ) ) ; // TODO: Prevent copy here.
256318 }
257319
258- #createMultichainAccount(
320+ async #createMultichainAccount(
259321 groupIndex : number ,
260- accounts : InternalAccount [ ] ,
261- ) : MultichainAccount {
262- const multichainAccount = new MultichainAccountAdapter ( {
263- walletId : this . id ,
322+ ) : Promise < MultichainAccount > {
323+ const multichainAccount = await MultichainAccountAdapter . from ( {
324+ wallet : this ,
325+ providers : this . #providers ,
264326 groupIndex,
265- accounts,
266327 } ) ;
267328
268329 // Register the account to our internal map.
@@ -286,20 +347,17 @@ export class MultichainAccountWalletAdapter implements MultichainAccountWallet {
286347 ) ;
287348 }
288349
289- const accounts : InternalAccount [ ] = [ ] ;
290350 for ( const provider of this . #providers) {
291- for ( const account of await provider . createAccounts ( {
351+ await provider . createAccounts ( {
292352 entropySource : this . #entropySource,
293353 groupIndex,
294- } ) ) {
295- accounts . push ( account ) ;
296- }
354+ } ) ;
297355 }
298356
299357 // Re-create and "refresh" the multichain account (we assume all account creations are
300358 // idempotent, so we should get the same accounts and potentially some new accounts (if
301359 // some account providers decide to return more of them this time).
302- return this . #createMultichainAccount( groupIndex , accounts ) ;
360+ return await this . #createMultichainAccount( groupIndex ) ;
303361 }
304362
305363 async createNextMultichainAccount ( ) : Promise < MultichainAccount > {
@@ -339,17 +397,15 @@ export class MultichainAccountWalletAdapter implements MultichainAccountWallet {
339397 // We only create missing accounts if one of the provider has discovered
340398 // and created accounts.
341399 for ( const provider of missingProviders ) {
342- const missingAccounts = await provider . createAccounts ( {
400+ await provider . createAccounts ( {
343401 entropySource : this . #entropySource,
344402 groupIndex,
345403 } ) ;
346-
347- accounts = accounts . concat ( missingAccounts ) ;
348404 }
349405
350406 // We've got all the accounts now, we can create our multichain account.
351407 multichainAccounts . push (
352- this . #createMultichainAccount( groupIndex , accounts ) ,
408+ await this . #createMultichainAccount( groupIndex ) ,
353409 ) ;
354410
355411 // We have accounts, we need to check the next index.
0 commit comments