Skip to content

Commit

Permalink
feat: add an adapter for Hub for wallets-react and enabling Hub by de…
Browse files Browse the repository at this point in the history
…fault.
  • Loading branch information
yeager-eren committed Oct 30, 2024
1 parent 1ce3367 commit 9355468
Show file tree
Hide file tree
Showing 81 changed files with 2,910 additions and 918 deletions.
1 change: 0 additions & 1 deletion queue-manager/rango-preset/src/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export type WalletBalance = {
};

export type Account = {
balances: WalletBalance[] | null;
address: string;
loading: boolean;
walletType: WalletType;
Expand Down
6 changes: 1 addition & 5 deletions queue-manager/rango-preset/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,8 @@ export interface SwapQueueContext extends QueueContext {
switchNetwork: (
wallet: WalletType,
network: Network
) => Promise<ConnectResult | undefined> | undefined;
) => Promise<ConnectResult | ConnectResult[] | undefined> | undefined;
canSwitchNetworkTo: (type: WalletType, network: Network) => boolean;
connect: (
wallet: WalletType,
network: Network
) => Promise<ConnectResult> | undefined;
state: (type: WalletType) => WalletState;
isMobileWallet: (type: WalletType) => boolean;

Expand Down
3 changes: 3 additions & 0 deletions wallets/core/src/hub/mod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export { Namespace } from './namespaces/mod.js';

export { Provider } from './provider/mod.js';
export type { CommonNamespaces, CommonNamespaceKeys } from './provider/mod.js';

export { Hub } from './hub.js';
export type { Store, State, ProviderInfo } from './store/mod.js';
export {
Expand Down
5 changes: 4 additions & 1 deletion wallets/core/src/hub/namespaces/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,10 @@ class Namespace<T extends Actions<T>> {
return orAction(context, prev);
}, actionError);
} catch (orError) {
throw new Error(OR_ELSE_ACTION_FAILED_ERROR(actionName.toString()), {
const errorMessage = OR_ELSE_ACTION_FAILED_ERROR(
`${actionName.toString()} for ${this.namespaceId} namespace.`
);
throw new Error(errorMessage, {
cause: actionError,
});
}
Expand Down
1 change: 1 addition & 0 deletions wallets/core/src/hub/provider/mod.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export type {
ExtendableInternalActions,
CommonNamespaces,
CommonNamespaceKeys,
State,
Context,
ProviderBuilderOptions,
Expand Down
8 changes: 6 additions & 2 deletions wallets/core/src/hub/provider/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { FindProxiedNamespace } from '../../builders/mod.js';
import type { Store } from '../../hub/mod.js';
import type { LegacyState } from '../../legacy/mod.js';
import type { NamespaceInterface, Store } from '../../mod.js';
import type { CosmosActions } from '../../namespaces/cosmos/mod.js';
import type { EvmActions } from '../../namespaces/evm/mod.js';
import type { SolanaActions } from '../../namespaces/solana/mod.js';
import type { AnyFunction, FunctionWithContext } from '../../types/actions.js';
import type { Prettify } from '../../types/utils.js';

export type Context = {
state: () => [GetState, SetState];
Expand All @@ -25,13 +27,15 @@ export interface CommonNamespaces {
cosmos: CosmosActions;
}

export type CommonNamespaceKeys = Prettify<keyof CommonNamespaces>;

export interface ExtendableInternalActions {
init?: FunctionWithContext<AnyFunction, Context>;
}

export type RegisteredNamespaces<K extends keyof T, T> = Map<
K,
NamespaceInterface<K, T>
FindProxiedNamespace<K, T>
>;

export type ProviderBuilderOptions = { store?: Store };
12 changes: 3 additions & 9 deletions wallets/core/src/hub/store/providers.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import type {
CommonNamespaces,
State as InternalProviderState,
} from '../provider/mod.js';
import type { State as InternalProviderState } from '../provider/mod.js';
import type { CommonNamespaceKeys } from '../provider/types.js';
import type { StateCreator } from 'zustand';

import { produce } from 'immer';

import { guessProviderStateSelector, type State } from './mod.js';

type NamespaceName =
| keyof CommonNamespaces
| Omit<string, keyof CommonNamespaces>;

type Browsers = 'firefox' | 'chrome' | 'edge' | 'brave' | 'homepage';
type Property<N extends string, V> = { name: N; value: V };
type DetachedInstances = Property<'detached', NamespaceName[]>;
type DetachedInstances = Property<'detached', CommonNamespaceKeys[]>;

export type ProviderInfo = {
name: string;
Expand Down
9 changes: 9 additions & 0 deletions wallets/core/src/legacy/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export type {
InstallObjects as LegacyInstallObjects,
WalletInfo as LegacyWalletInfo,
ConnectResult as LegacyConnectResult,
NamespaceInputForConnect as LegacyNamespaceInputForConnect,
NamespaceInputWithDiscoverMode as LegacyNamespaceInputWithDiscoverMode,
} from './types.js';

export {
Expand All @@ -35,5 +37,12 @@ export { Persistor } from './persistor.js';
export {
readAccountAddress as legacyReadAccountAddress,
getBlockChainNameFromId as legacyGetBlockChainNameFromId,
formatAddressWithNetwork as legacyFormatAddressWithNetwork,
} from './helpers.js';
export { default as LegacyWallet } from './wallet.js';

export {
eagerConnectHandler as legacyEagerConnectHandler,
isNamespaceDiscoverMode as legacyIsNamespaceDiscoverMode,
isEvmNamespace as legacyIsEvmNamespace,
} from './utils.js';
42 changes: 42 additions & 0 deletions wallets/core/src/legacy/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ export type WalletInfo = {
name: string;
img: string;
installLink: InstallObjects | string;
/**
* @deprecated we don't use this value anymore.
*/
color: string;
supportedChains: BlockchainMeta[];
showOnMobile?: boolean;
Expand Down Expand Up @@ -202,6 +205,12 @@ export type CanEagerConnect = (options: {
meta: BlockchainMeta[];
}) => Promise<boolean>;

export type EagerConnectResult<I = unknown> = {
accounts: string[] | null;
network: string | null;
provider: I | null;
};

export interface WalletActions {
connect: Connect;
getInstance: any;
Expand Down Expand Up @@ -235,3 +244,36 @@ export type WalletProviders = Map<
>;

export type ProviderInterface = { config: WalletConfig } & WalletActions;

// it comes from wallets.ts and `connect`
type NetworkTypeFromLegacyConnect = Network | undefined;

export type NetworkTypeForNamespace<T extends NamespacesWithDiscoverMode> =
T extends 'DISCOVER_MODE'
? string
: T extends Namespace
? NetworkTypeFromLegacyConnect
: never;

export type NamespacesWithDiscoverMode = Namespace | 'DISCOVER_MODE';

export type NamespaceInputWithDiscoverMode = {
namespace: 'DISCOVER_MODE';
network: string;
derivationPath?: string;
};

export type NamespaceInputForConnect<T extends Namespace = Namespace> =
| {
/**
* By default, you should specify namespace (e.g. evm).
* For backward compatibility with legacy implementation, DISCOVER_MODE will try to map a list of known (and hardcoded) networks to a namespace.
*/
namespace: T;
/**
* In some cases, we need to connect a specific network on a namespace. e.g. Polygon on EVM.
*/
network: NetworkTypeForNamespace<T>;
derivationPath?: string;
}
| NamespaceInputWithDiscoverMode;
31 changes: 31 additions & 0 deletions wallets/core/src/legacy/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type {
NamespaceInputForConnect,
NamespaceInputWithDiscoverMode,
} from './types.js';

import { Namespace } from './types.js';

export async function eagerConnectHandler<R = unknown>(params: {
canEagerConnect: () => Promise<boolean>;
connectHandler: () => Promise<R>;
providerName: string;
}) {
// Check if we can eagerly connect to the wallet
if (await params.canEagerConnect()) {
// Connect to wallet as usual
return await params.connectHandler();
}
throw new Error(`can't restore connection for ${params.providerName}.`);
}

export function isNamespaceDiscoverMode(
namespace: NamespaceInputForConnect
): namespace is NamespaceInputWithDiscoverMode {
return namespace.namespace === 'DISCOVER_MODE';
}

export function isEvmNamespace(
namespace: NamespaceInputForConnect
): namespace is NamespaceInputForConnect<Namespace.Evm> {
return namespace.namespace === Namespace.Evm;
}
45 changes: 29 additions & 16 deletions wallets/core/src/legacy/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {
EagerConnectResult,
GetInstanceOptions,
NamespaceData,
Network,
Expand All @@ -14,6 +15,7 @@ import {
needsCheckInstallation,
} from './helpers.js';
import { Events, Networks } from './types.js';
import { eagerConnectHandler } from './utils.js';

export type EventHandler = (
type: WalletType,
Expand All @@ -26,11 +28,16 @@ export type EventHandler = (
export type EventInfo = {
supportedBlockchains: BlockchainMeta[];
isContractWallet: boolean;
// This is for Hub and be able to make it compatible with legacy behavior.
isHub: boolean;
};

export interface State {
connected: boolean;
connecting: boolean;
/**
* @depreacted it always returns `false`. don't use it.
*/
reachable: boolean;
installed: boolean;
accounts: string[] | null;
Expand All @@ -57,6 +64,7 @@ class Wallet<InstanceType = any> {
this.info = {
supportedBlockchains: [],
isContractWallet: false,
isHub: false,
};
this.state = {
connected: false,
Expand Down Expand Up @@ -264,26 +272,30 @@ class Wallet<InstanceType = any> {
}

// This method is only used for auto connection
async eagerConnect() {
async eagerConnect(): Promise<EagerConnectResult<InstanceType>> {
const instance = await this.tryGetInstance({ network: undefined });
const { canEagerConnect } = this.actions;
const error_message = `can't restore connection for ${this.options.config.type} .`;
const providerName = this.options.config.type;

if (canEagerConnect) {
// Check if we can eagerly connect to the wallet
const eagerConnection = await canEagerConnect({
instance: instance,
meta: this.info.supportedBlockchains,
});
return await eagerConnectHandler({
canEagerConnect: async () => {
if (!canEagerConnect) {
throw new Error(
`${providerName} provider hasn't implemented canEagerConnect.`
);
}

if (eagerConnection) {
// Connect to wallet as usual
return this.connect();
}
throw new Error(error_message);
} else {
throw new Error(error_message);
}
return await canEagerConnect({
instance: instance,
meta: this.info.supportedBlockchains,
});
},
connectHandler: async () => {
const result = await this.connect();
return result;
},
providerName,
});
}

async getSigners(provider: any) {
Expand Down Expand Up @@ -408,6 +420,7 @@ class Wallet<InstanceType = any> {
const eventInfo: EventInfo = {
supportedBlockchains: this.info.supportedBlockchains,
isContractWallet: this.info.isContractWallet,
isHub: false,
};
this.options.handler(
this.options.config.type,
Expand Down
16 changes: 10 additions & 6 deletions wallets/core/src/mod.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
export type { Store, State, ProviderInfo } from './hub/mod.js';
export type {
Store,
State,
ProviderInfo,
CommonNamespaces,
CommonNamespaceKeys,
} from './hub/mod.js';
export {
Hub,
Provider,
Expand All @@ -7,10 +13,8 @@ export {
guessProviderStateSelector,
namespaceStateSelector,
} from './hub/mod.js';
export type {
ProxiedNamespace,
FindProxiedNamespace as NamespaceInterface,
} from './builders/mod.js';

export type { ProxiedNamespace, FindProxiedNamespace } from './builders/mod.js';
export {
NamespaceBuilder,
ProviderBuilder,
Expand All @@ -31,5 +35,5 @@ export {
* To make it work for Parcel, we should go with second mentioned option.
*
*/
export type { Versions } from './utils/mod.js';
export type { VersionedProviders } from './utils/mod.js';
export { defineVersions, pickVersion } from './utils/mod.js';
6 changes: 6 additions & 0 deletions wallets/core/src/namespaces/common/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ export {
recommended as andRecommended,
} from './and.js';
export { intoConnecting, recommended as beforeRecommended } from './before.js';

export type {
CaipAccount,
Accounts,
AccountsWithActiveChain,
} from '../../types/accounts.js';
1 change: 1 addition & 0 deletions wallets/core/src/namespaces/cosmos/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export interface CosmosActions
extends AutoImplementedActionsByRecommended,
CommonActions {
// TODO
connect: () => Promise<string>;
}
Loading

0 comments on commit 9355468

Please sign in to comment.