Skip to content

Commit

Permalink
refactor: wallet aggregation
Browse files Browse the repository at this point in the history
  • Loading branch information
tien committed Nov 13, 2024
1 parent e5c37d0 commit 9f3e3af
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 10 deletions.
5 changes: 5 additions & 0 deletions .changeset/selfish-keys-know.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@reactive-dot/core": patch
---

Refactored wallet aggregation logic.
66 changes: 66 additions & 0 deletions packages/core/src/actions/aggregate-wallets.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type { PolkadotSignerAccount } from "../wallets/account.js";
import { WalletProvider } from "../wallets/provider.js";
import { Wallet } from "../wallets/wallet.js";
import { aggregateWallets } from "./aggregate-wallets.js";
import { Observable } from "rxjs";
import { it, expect } from "vitest";

class MockWallet extends Wallet {
id = "mock";

name = "Mock";

initialize() {
throw new Error("Method not implemented.");
}

connected$ = new Observable<boolean>();

connect() {
throw new Error("Method not implemented.");
}

disconnect() {
throw new Error("Method not implemented.");
}

accounts$ = new Observable<PolkadotSignerAccount[]>();
}

class MockProvider extends WalletProvider {
getWallets() {
return Array.from({ length: 10 }).map(() => new MockWallet());
}
}

it("aggregates wallets from provider", async () => {
const wallets = await aggregateWallets([
new MockWallet(),
new MockProvider(),
]);

expect(wallets).toHaveLength(11);

for (const wallet of wallets) {
expect(wallet).toBeInstanceOf(Wallet);
}
});

it("only aggregate once", async () => {
const walletsAndProviders = [
new MockWallet(),
new MockProvider(),
new MockWallet(),
new MockProvider(),
];

const firstRunWallets = await aggregateWallets(walletsAndProviders);

const secondRunWallets = await aggregateWallets(walletsAndProviders);

expect(firstRunWallets).toHaveLength(secondRunWallets.length);

for (const [index, wallet] of firstRunWallets.entries()) {
expect(wallet).toBe(secondRunWallets.at(index));
}
});
8 changes: 7 additions & 1 deletion packages/core/src/actions/aggregate-wallets.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { Wallet, type WalletProvider } from "../wallets/index.js";

const providerWallets = new WeakMap<WalletProvider, Wallet[]>();

export function aggregateWallets(
providersOrWallets: ReadonlyArray<Wallet | WalletProvider>,
) {
return Promise.all(
providersOrWallets.map((walletOrProvider) =>
walletOrProvider instanceof Wallet
? [walletOrProvider]
: walletOrProvider.getOrFetchWallets(),
: (async () =>
providerWallets.get(walletOrProvider) ??
providerWallets
.set(walletOrProvider, await walletOrProvider.getWallets())
.get(walletOrProvider)!)(),
),
).then((wallets) => wallets.flat());
}
9 changes: 0 additions & 9 deletions packages/core/src/wallets/provider.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
import type { Wallet } from "./wallet.js";

export abstract class WalletProvider {
#wallets: Wallet[] | undefined;

abstract getWallets(): Wallet[] | Promise<Wallet[]>;

/**
* @internal
*/
async getOrFetchWallets() {
return (this.#wallets ??= await this.getWallets());
}
}

0 comments on commit 9f3e3af

Please sign in to comment.