Management API Reference

Ecosystem wallet

Quickstart your wallet

This guide and the configuration sections are to help developers launch their own ecosystem wallet. If you're looking to use an existing ecosystem wallet SDK, please refer to the usage section and install the specific ecosystem package.

The Fort SDK is the easiest way to create you ecosystem wallet. It comes with a code-splitting environment, all the necessary tools to make your wallet SDK a reality. It is the easier way to create your own ecosystem wallet.

The Fort SDK has two main parts:

  1. @openfort/ecosystem-js/client: The Client SDK that you will use to create your wallet SDK.
  2. @openfort/ecosystem-js/core: The Core SDK that you will use to create your wallet UI. Fort also includes a React specific package @openfort/ecosystem-js/react that you can use to get started faster.

0. Requirements#

Your project will need some specific configuration to enable code splitting:

  • Typescript version 5.0.2 or higher.
  • TS Config needs to have compilerOptions.moduleResolution set to bundler.
  • Your code editor and project should have the same version of Typescript.

1. Install the Fort SDK#

Install the latest version of Fort SDK using your package manager of choice:

You will need to install @openfort/ecosystem-js at both your wallet SDK and wallet UI projects.

Terminal

_10
npm install @openfort/ecosystem-js

2. Set your auth providers#

Navigate to the auth providers page on the Openfort dashboard by selecting your project and then clicking Auth providers Methods in the side bar in the players page. Select the account types you'd like users to be able to login with. For more information on how to enable social logins, check out the dashboard docs.

3. Get your Openfort API keys#

From the Openfort Dashboard for select your desired app, navigate to the developers page in the top bar. On the de tab, find the API keys section. Get your Openfort API keys, you will need it in the next step.

You will find two keys:

  • Publishable Key: This value can be safely exposed in a client-side environment.
  • Secret Key: This value should never be exposed in a client-side environment. It should be kept secure and used only in a server-side environment. Learn more on how to use it in the server-side guide. You can further secure it for production applications.

To generate non custodial wallets, you will need to create a Shield instance. At the API keys page, scroll down to the Shield section and click on the Create Shield keys button. A one time pop-up will appear with a variable called encryption share. Its very important that you store it safely. You will not be able to see it again.

Then, in your page, you will see two Shield keys:

  • Publishable Key: This value can be safely exposed in a client-side environment.
  • Secret Key: This value should never be exposed in a client-side environment.

4. Creating your wallet SDK#

fort-architecture-1

The easiest way to get started is to create a Proxy object in order to map the already provided functionality of the Client SDK. You can nevertheless change or add new methods to fit your needs.

Getting the ecosystem id

When creating your client SDK you need to add the ecosystem ID. It can be found in their dashboard at the settings section. The ecosystemWalletDomain is the domain where your wallet UI is hosted.

main.ts
package.json
tsconfig.json

_26
// See your ecosystem id here: https://dashboard.openfort.xyz/settings/project/overview
_26
import { AppMetadata, Client } from "@openfort/ecosystem-js/client";
_26
_26
class EcosystemWallet extends Client {
_26
constructor(appMetadata?: AppMetadata) {
_26
super({
_26
baseConfig: {
_26
ecosystemWalletDomain: 'https://id.sample.openfort.xyz',
_26
ecosystemId: 'test-226353cd-dd0e-4fba-8208-58dfe29d3581',
_26
},
_26
appMetadata,
_26
});
_26
_26
return new Proxy(this, {
_26
get: (target, prop) => {
_26
if (prop in target) {
_26
const value = target[prop as keyof EcosystemWallet];
_26
return typeof value === 'function' ? value.bind(target) : value;
_26
}
_26
return undefined;
_26
}
_26
});
_26
}
_26
}
_26
_26
export default EcosystemWallet;

You're all set! By running the build script you'll get a dist folder with the compiled code. You can now publish your package to npm and share it with the world.

You can check all the available client methods in the Client SDK reference.

5. Creating your wallet UI#

The wallet UI is where your users will interact with your wallet.

fort-architecture-2

Openfort @openfort/ecosystem-js comes with a set of pre-built components that you can use to create your wallet UI. To learn how to customize it further, head to the UI screens guide.

In your project, import the FortProvider component and wrap your app with it. Set the publishable key field to you got from the Dashboard in step 3.

Concretely, the FortProvider must wrap any component or page that will use the Fort SDK in your react app. It is generally recommended to render it as close to the root of your application as possible.

For example, in a NextJS or Create React App project, you may wrap your components like so:

App.tsx
Loading.tsx

_75
// Set your publishable key, shield publishable key and ecosystem id. Remember to switch to your live secret key in production.
_75
// See your keys here: https://dashboard.openfort.xyz/developers/api-keys
_75
// See your ecosystem ID here: https://dashboard.openfort.xyz/settings/project/overview
_75
import {
_75
WalletGrantPermissions,
_75
WalletSendCalls,
_75
EthRequestAccounts,
_75
AppState,
_75
EthSendTransaction,
_75
EthSignTypedDataV4,
_75
FortProvider,
_75
PersonalSign,
_75
withAuthenticationRequired,
_75
Settings,
_75
UnsupportedMethod,
_75
WalletShowCalls,
_75
darkFortTheme
_75
} from '@openfort/ecosystem-js/react';
_75
import { Route, Routes, useNavigate } from 'react-router-dom';
_75
_75
async function getShieldSession(accessToken:string):Promise<string> {
_75
const response = await fetch(`${process.env.REACT_APP_BACKEND_URL!}/api/protected-create-encryption-session`, {
_75
method: 'POST',
_75
headers: {
_75
'Content-Type': 'application/json',
_75
'Authorization': `Bearer ${accessToken}`
_75
}
_75
});
_75
_75
if (!response.ok) {
_75
throw new Error('Failed to fetch shield session');
_75
}
_75
_75
const data = await response.json();
_75
return data.session;
_75
}
_75
_75
const ProtectedRoute = ({ component, ...args }: any) => {
_75
const Component = withAuthenticationRequired(component, {
_75
onRedirecting: () => <Loading />,
_75
});
_75
return <Component {...args} />;
_75
};
_75
_75
export default function Providers({children}: {children: React.ReactNode}) {
_75
const nav = useNavigate()
_75
return (
_75
<FortProvider
_75
appName={process.env.REACT_APP_APP_NAME}
_75
supportedChains={[80002]}
_75
appearance={darkFortTheme}
_75
logoUrl='https://purple-magnificent-bat-958.mypinata.cloud/ipfs/QmfQrh2BiCzugFauYF9Weu9SFddsVh9qV82uw43cxH8UDV'
_75
onRedirectCallback={(appState?: AppState) => nav((appState && appState.returnTo) || window.location.pathname)}
_75
publishableKey={process.env.REACT_APP_OPENFORT_PUBLIC_KEY!}
_75
ecosystemId={process.env.REACT_APP_OPENFORT_ECOSYSTEM_ID!}
_75
shieldConfig={{
_75
shieldPublishableKey: process.env.REACT_APP_SHIELD_PUBLIC_KEY!,
_75
getShieldSession: getShieldSession
_75
}}
_75
>
_75
<Routes>
_75
<Route path='/sign/personal-sign' element={<ProtectedRoute component={PersonalSign} />} />
_75
<Route path='/sign/eth-sign-typed-data-v-4' element={<ProtectedRoute component={EthSignTypedDataV4} />} />
_75
<Route path='/sign/eth-send-transaction' element={<ProtectedRoute component={EthSendTransaction} />} />
_75
<Route path='/sign/wallet-show-calls' element={<ProtectedRoute component={WalletShowCalls} />} />
_75
<Route path='/sign/wallet-grant-permissions' element={<ProtectedRoute component={WalletGrantPermissions} />} />
_75
<Route path='/sign/wallet-send-calls' element={<ProtectedRoute component={WalletSendCalls} />} />
_75
<Route path='/sign/eth-request-accounts' element={<ProtectedRoute component={EthRequestAccounts} />} />
_75
<Route path='/settings' element={<ProtectedRoute component={Settings} />} />
_75
<Route path='/' element={<ProtectedRoute component={Loading} />} />
_75
<Route path='*' element={<UnsupportedMethod />} />
_75
</Routes>
_75
</FortProvider>
_75
);
_75
}

Check all the available core methods in the Core SDK reference.