-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): option to enable Substrate Connect support (#538)
- Loading branch information
Showing
3 changed files
with
201 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@reactive-dot/core": minor | ||
--- | ||
|
||
Added option to enable Substrate Connect support. |
171 changes: 116 additions & 55 deletions
171
packages/core/src/providers/light-client/provider.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,144 @@ | ||
import { | ||
createClientFromLightClientProvider, | ||
createLightClientProvider, | ||
isLightClientProvider, | ||
createClientFromLightClientProvider, | ||
type LightClientProvider, | ||
} from "./provider.js"; | ||
import { it, expect, beforeEach, vi } from "vitest"; | ||
import { beforeEach, describe, expect, it, vi } from "vitest"; | ||
|
||
// Create fake implementations for dependencies | ||
vi.mock("polkadot-api", () => ({ | ||
createClient: vi.fn().mockReturnValue({ mockClient: true }), | ||
})); | ||
|
||
const fakeSmoldot = { | ||
addChain: vi.fn((chain: string | { chainSpec: string }) => | ||
Promise.resolve({ chainSpec: chain, id: "added" }), | ||
), | ||
}; | ||
vi.mock("polkadot-api/sm-provider", () => ({ | ||
getSmProvider: vi.fn().mockImplementation((chain) => ({ | ||
provider: true, | ||
chain, | ||
})), | ||
})); | ||
|
||
// Mock @substrate/smoldot-discovery to return a fake smoldot provider | ||
vi.mock("@substrate/smoldot-discovery", () => ({ | ||
getSmoldotExtensionProviders: () => [ | ||
{ provider: Promise.resolve(fakeSmoldot) }, | ||
], | ||
vi.mock("./wellknown-chains.js", () => ({ | ||
wellknownChains: { | ||
polkadot: [ | ||
vi.fn().mockResolvedValue({ chainSpec: "polkadot-spec" }), | ||
{ | ||
polkadot_asset_hub: vi | ||
.fn() | ||
.mockResolvedValue({ chainSpec: "asset-hub-spec" }), | ||
}, | ||
], | ||
kusama: [ | ||
vi.fn().mockResolvedValue({ chainSpec: "kusama-spec" }), | ||
{ | ||
polkadot_asset_hub: vi | ||
.fn() | ||
.mockResolvedValue({ chainSpec: "asset-hub-kusama-spec" }), | ||
}, | ||
], | ||
}, | ||
})); | ||
|
||
// Mock polkadot-api/sm-provider to wrap chains in a fake provider | ||
vi.mock("polkadot-api/sm-provider", () => ({ | ||
getSmProvider: vi.fn((chain) => Promise.resolve({ clientChain: chain })), | ||
global.Worker = class { | ||
constructor() {} | ||
postMessage = vi.fn(); | ||
addEventListener = vi.fn(); | ||
} as unknown as typeof Worker; | ||
|
||
// Mock smoldot imports | ||
vi.mock("polkadot-api/smoldot/from-worker", () => ({ | ||
startFromWorker: vi.fn().mockResolvedValue({ | ||
addChain: vi.fn().mockImplementation(({ chainSpec }) => ({ | ||
chainId: "chain-id", | ||
chainSpec, | ||
})), | ||
}), | ||
})); | ||
|
||
// Mock polkadot-api to return a fake client with the provided provider | ||
vi.mock("polkadot-api", () => ({ | ||
createClient: vi.fn((provider) => ({ sm_client: provider })), | ||
vi.mock("@substrate/smoldot-discovery", () => ({ | ||
getSmoldotExtensionProviders: vi.fn().mockReturnValue([ | ||
{ | ||
provider: { | ||
addChain: vi.fn().mockImplementation((chainSpec) => ({ | ||
chainId: "sc-chain-id", | ||
chainSpec, | ||
})), | ||
}, | ||
}, | ||
]), | ||
})); | ||
|
||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
}); | ||
describe("Light Client Provider", () => { | ||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
}); | ||
|
||
it("should create a relay chain provider with chainSpec", async () => { | ||
const lightClient = createLightClientProvider(); | ||
const relayProvider = lightClient.addRelayChain({ | ||
chainSpec: "fakeRelayChainSpec", | ||
it("should create a light client provider without substrate connect", async () => { | ||
const provider = createLightClientProvider(); | ||
|
||
expect(provider).toBeDefined(); | ||
expect(provider.addRelayChain).toBeInstanceOf(Function); | ||
}); | ||
|
||
const client = await createClientFromLightClientProvider(relayProvider); | ||
it("should create a light client provider with substrate connect enabled", async () => { | ||
const provider = createLightClientProvider({ | ||
useExtensionProvider: true, | ||
}); | ||
|
||
// Expect the fake sm-provider to have been called with the result of smoldot.addChain. | ||
expect(client).toEqual({ | ||
sm_client: { | ||
clientChain: { chainSpec: "fakeRelayChainSpec", id: "added" }, | ||
}, | ||
expect(provider).toBeDefined(); | ||
expect(provider.addRelayChain).toBeInstanceOf(Function); | ||
}); | ||
expect(fakeSmoldot.addChain).toHaveBeenCalledWith("fakeRelayChainSpec"); | ||
}); | ||
|
||
it("should create a parachain provider with chainSpec", async () => { | ||
const lightClient = createLightClientProvider(); | ||
const relayProvider = lightClient.addRelayChain({ | ||
chainSpec: "fakeRelayChainSpec", | ||
it("should add relay chain with chain spec", async () => { | ||
const provider = createLightClientProvider(); | ||
const relayChain = provider.addRelayChain({ chainSpec: "test-chain-spec" }); | ||
|
||
expect(relayChain).toBeDefined(); | ||
expect(isLightClientProvider(relayChain)).toBeTruthy(); | ||
}); | ||
const parachainProvider = relayProvider.addParachain({ | ||
chainSpec: "fakeParachainSpec", | ||
|
||
it("should add relay chain with wellknown id", async () => { | ||
const provider = createLightClientProvider(); | ||
const relayChain = provider.addRelayChain({ id: "polkadot" }); | ||
|
||
expect(relayChain).toBeDefined(); | ||
expect(isLightClientProvider(relayChain)).toBeTruthy(); | ||
}); | ||
|
||
const client = await createClientFromLightClientProvider(parachainProvider); | ||
it("should add parachain to relay chain", async () => { | ||
const provider = createLightClientProvider(); | ||
const relayChain = provider.addRelayChain({ id: "polkadot" }); | ||
const parachain = relayChain.addParachain({ id: "polkadot_asset_hub" }); | ||
|
||
// Expect the parachain chain addition to use its own chainSpec. | ||
expect(client).toEqual({ | ||
sm_client: { | ||
clientChain: { chainSpec: "fakeParachainSpec", id: "added" }, | ||
}, | ||
expect(parachain).toBeDefined(); | ||
expect(isLightClientProvider(parachain)).toBeTruthy(); | ||
}); | ||
expect(fakeSmoldot.addChain).toHaveBeenCalledTimes(2); | ||
}); | ||
|
||
it("should recognize a valid LightClientProvider", () => { | ||
const lightClient = createLightClientProvider(); | ||
const relayProvider = lightClient.addRelayChain({ | ||
chainSpec: "fakeRelayChainSpec", | ||
it("should add parachain with chain spec to relay chain", async () => { | ||
const provider = createLightClientProvider(); | ||
const relayChain = provider.addRelayChain({ id: "polkadot" }); | ||
const parachain = relayChain.addParachain({ chainSpec: "parachain-spec" }); | ||
|
||
expect(parachain).toBeDefined(); | ||
expect(isLightClientProvider(parachain)).toBeTruthy(); | ||
}); | ||
const nonProvider = {}; | ||
|
||
expect(isLightClientProvider(relayProvider)).toBe(true); | ||
expect(isLightClientProvider(nonProvider)).toBe(false); | ||
it("should identify light client providers correctly", () => { | ||
const provider = createLightClientProvider(); | ||
const relayChain = provider.addRelayChain({ id: "polkadot" }); | ||
|
||
expect(isLightClientProvider(relayChain)).toBeTruthy(); | ||
expect(isLightClientProvider({})).toBeFalsy(); | ||
expect(isLightClientProvider(null)).toBeFalsy(); | ||
expect(isLightClientProvider(undefined)).toBeFalsy(); | ||
}); | ||
|
||
it("should create client from light client provider", () => { | ||
const provider = createLightClientProvider(); | ||
const relayChain = provider.addRelayChain({ id: "polkadot" }); | ||
const client = createClientFromLightClientProvider( | ||
relayChain as LightClientProvider, | ||
); | ||
|
||
expect(client).toEqual({ mockClient: true }); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters