-
Notifications
You must be signed in to change notification settings - Fork 11.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[dapp-kit] Add ability to configure networks to SuiClientProvider (#1…
…3342) ## Description This is getting into react stuff where I am not very confident I know what I am doing. The goal here is to provide a Context provider that supports switching between networks, and allows providing either pre-configured SuiClients for each network, or a config object (with customizable options) that can be used to create a client. ## Test Plan How did you test the new or updated feature? --- If your changes are not user-facing and not a breaking change, you can skip the following section. Otherwise, please indicate what changed, and then add to the Release Notes section as highlighted during the release process. ### Type of Change (Check all that apply) - [ ] protocol change - [ ] user-visible impact - [ ] breaking change for a client SDKs - [ ] breaking change for FNs (FN binary must upgrade) - [ ] breaking change for validators or node operators (must upgrade binaries) - [ ] breaking change for on-chain data layout - [ ] necessitate either a data wipe or data migration ### Release notes
- Loading branch information
1 parent
3a4ccc7
commit ee9af1a
Showing
11 changed files
with
203 additions
and
37 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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,30 +1,70 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { SuiClient, getFullnodeUrl } from '@mysten/sui.js/client'; | ||
import { SuiClientContext } from '../hooks/useSuiClient.js'; | ||
import { useMemo } from 'react'; | ||
import { SuiClient, getFullnodeUrl, isSuiClient } from '@mysten/sui.js/client'; | ||
import type { SuiClientOptions } from '@mysten/sui.js/client'; | ||
import { createContext, useMemo, useState } from 'react'; | ||
|
||
export interface SuiClientProviderProps { | ||
type NetworkConfig = SuiClient | SuiClientOptions; | ||
type NetworkConfigs<T extends NetworkConfig = NetworkConfig> = Record<string, T>; | ||
|
||
export interface SuiClientProviderContext { | ||
client: SuiClient; | ||
networks: NetworkConfigs; | ||
selectedNetwork: string; | ||
selectNetwork: (network: string) => void; | ||
} | ||
|
||
export const SuiClientContext = createContext<SuiClientProviderContext | null>(null); | ||
|
||
export interface SuiClientProviderProps<T extends NetworkConfigs> { | ||
networks?: T; | ||
createClient?: (name: keyof T, config: T[keyof T]) => SuiClient; | ||
defaultNetwork?: keyof T & string; | ||
children: React.ReactNode; | ||
client?: SuiClient; | ||
url?: string; | ||
queryKeyPrefix: string; | ||
} | ||
|
||
export const SuiClientProvider = (props: SuiClientProviderProps) => { | ||
const ctx = useMemo(() => { | ||
const client = | ||
props.client ?? | ||
new SuiClient({ | ||
url: props.url ?? getFullnodeUrl('devnet'), | ||
}); | ||
const DEFAULT_NETWORKS = { | ||
localnet: { url: getFullnodeUrl('localnet') }, | ||
}; | ||
|
||
const DEFAULT_CREATE_CLIENT = function createClient( | ||
_name: string, | ||
config: NetworkConfig | SuiClient, | ||
) { | ||
if (isSuiClient(config)) { | ||
return config; | ||
} | ||
|
||
return new SuiClient(config); | ||
}; | ||
|
||
export function SuiClientProvider<T extends NetworkConfigs>(props: SuiClientProviderProps<T>) { | ||
const networks = (props.networks ?? DEFAULT_NETWORKS) as T; | ||
const createClient = | ||
(props.createClient as typeof DEFAULT_CREATE_CLIENT) ?? DEFAULT_CREATE_CLIENT; | ||
|
||
const [selectedNetwork, setSelectedNetwork] = useState<keyof T & string>( | ||
props.defaultNetwork ?? (Object.keys(networks)[0] as keyof T & string), | ||
); | ||
|
||
const [client, setClient] = useState<SuiClient>(() => { | ||
return createClient(selectedNetwork, networks[selectedNetwork]); | ||
}); | ||
|
||
const ctx = useMemo((): SuiClientProviderContext => { | ||
return { | ||
client, | ||
queryKey: (key: unknown[]) => [props.queryKeyPrefix, ...key], | ||
networks, | ||
selectedNetwork, | ||
selectNetwork: (network) => { | ||
if (network !== selectedNetwork) { | ||
setSelectedNetwork(network); | ||
setClient(createClient(network, networks[network])); | ||
} | ||
}, | ||
}; | ||
}, [props.client, props.url, props.queryKeyPrefix]); | ||
}, [client, setClient, createClient, selectedNetwork, networks]); | ||
|
||
return <SuiClientContext.Provider value={ctx}>{props.children}</SuiClientContext.Provider>; | ||
}; | ||
} |
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
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
104 changes: 104 additions & 0 deletions
104
sdk/dapp-kit/test/components/SuiClientProvider.test.tsx
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,104 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { render } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { screen } from '@testing-library/dom'; | ||
import { SuiClientProvider } from '../../src/components/SuiClientProvider.js'; | ||
import { useSuiClient, useSuiClientContext } from 'dapp-kit/src/index.js'; | ||
import { SuiClient } from '@mysten/sui.js/client'; | ||
import { useState } from 'react'; | ||
|
||
describe('SuiClientProvider', () => { | ||
it('renders without crashing', () => { | ||
render( | ||
<SuiClientProvider> | ||
<div>Test</div> | ||
</SuiClientProvider>, | ||
); | ||
expect(screen.getByText('Test')).toBeInTheDocument(); | ||
}); | ||
|
||
it('provides a SuiClient instance to its children', () => { | ||
const ChildComponent = () => { | ||
const client = useSuiClient(); | ||
expect(client).toBeInstanceOf(SuiClient); | ||
return <div>Test</div>; | ||
}; | ||
|
||
render( | ||
<SuiClientProvider> | ||
<ChildComponent /> | ||
</SuiClientProvider>, | ||
); | ||
}); | ||
|
||
it('can accept pre-configured SuiClients', () => { | ||
const suiClient = new SuiClient({ url: 'http://localhost:8080' }); | ||
const ChildComponent = () => { | ||
const client = useSuiClient(); | ||
expect(client).toBeInstanceOf(SuiClient); | ||
expect(client).toBe(suiClient); | ||
return <div>Test</div>; | ||
}; | ||
|
||
render( | ||
<SuiClientProvider networks={{ localnet: suiClient }}> | ||
<ChildComponent /> | ||
</SuiClientProvider>, | ||
); | ||
|
||
expect(screen.getByText('Test')).toBeInTheDocument(); | ||
}); | ||
|
||
test('can create sui clients with custom options', async () => { | ||
function NetworkSelector() { | ||
const ctx = useSuiClientContext(); | ||
|
||
return ( | ||
<div> | ||
{Object.keys(ctx.networks).map((network) => ( | ||
<button key={network} onClick={() => ctx.selectNetwork(network)}> | ||
{`select ${network}`} | ||
</button> | ||
))} | ||
</div> | ||
); | ||
} | ||
function CustomConfigProvider() { | ||
const [selectedNetwork, setSelectedNetwork] = useState<string>(); | ||
|
||
return ( | ||
<SuiClientProvider | ||
networks={{ | ||
a: { | ||
url: 'http://localhost:8080', | ||
custom: setSelectedNetwork, | ||
}, | ||
b: { | ||
url: 'http://localhost:8080', | ||
custom: setSelectedNetwork, | ||
}, | ||
}} | ||
createClient={(name, { custom, ...config }) => { | ||
custom(name); | ||
return new SuiClient(config); | ||
}} | ||
> | ||
<div>{`selected network: ${selectedNetwork}`}</div> | ||
<NetworkSelector /> | ||
</SuiClientProvider> | ||
); | ||
} | ||
|
||
const user = userEvent.setup(); | ||
|
||
render(<CustomConfigProvider />); | ||
|
||
expect(screen.getByText('selected network: a')).toBeInTheDocument(); | ||
|
||
await user.click(screen.getByText('select b')); | ||
|
||
expect(screen.getByText('selected network: b')).toBeInTheDocument(); | ||
}); | ||
}); |
File renamed without changes.
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,3 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
import '@testing-library/jest-dom'; |
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
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
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