Skip to content

Commit

Permalink
feat: add owallet (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryoid authored Mar 26, 2024
1 parent f9050e9 commit 944db24
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 2 deletions.
10 changes: 10 additions & 0 deletions examples/solid-vite/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
LeapController,
MetamaskInjectiveController,
NinjiController,
OWalletController,
StationController,
UnsignedTx,
WalletController,
Expand All @@ -33,6 +34,7 @@ const CHAINS: Record<string, string> = {
"injective-1": "Injective",
"pacific-1": "Sei",
"dymension_1100-1": "Dymension",
Oraichain: "Oraichain",
};
const WALLETS: Record<WalletName, string> = {
[WalletName.KEPLR]: "Keplr",
Expand All @@ -42,6 +44,7 @@ const WALLETS: Record<WalletName, string> = {
[WalletName.COMPASS]: "Compass",
[WalletName.METAMASK_INJECTIVE]: "MetaMask",
[WalletName.NINJI]: "Ninji",
[WalletName.OWALLET]: "OWallet",
};
const TYPES: Record<WalletType, string> = {
[WalletType.EXTENSION]: "Extension",
Expand All @@ -55,6 +58,7 @@ const CONTROLLERS: Record<string, WalletController> = {
[WalletName.COSMOSTATION]: new CosmostationController(WC_PROJECT_ID),
[WalletName.METAMASK_INJECTIVE]: new MetamaskInjectiveController(),
[WalletName.NINJI]: new NinjiController(),
[WalletName.OWALLET]: new OWalletController(),
};

function getRpc(chain: string): string {
Expand All @@ -79,6 +83,8 @@ function getRpc(chain: string): string {
return "https://rpc-sei-ia.cosmosia.notional.ventures";
case "dymension_1100-1":
return "https://rpc.dymension.nodestake.org";
case "Oraichain":
return "https://rpc.orai.io";
default:
throw new Error("Unknown chain");
}
Expand Down Expand Up @@ -106,6 +112,8 @@ function getGasPrice(chain: string): { amount: string; denom: string } {
return { amount: "0.1", denom: getDenom(chain) };
case "dymension_1100-1":
return { amount: "20000000000", denom: getDenom(chain) };
case "Oraichain":
return { amount: "0.003", denom: getDenom(chain) };
default:
throw new Error("Unknown chain");
}
Expand All @@ -132,6 +140,8 @@ function getDenom(chain: string): string {
return "usei";
case "dymension_1100-1":
return "adym";
case "Oraichain":
return "orai";
default:
throw new Error("Unknown chain");
}
Expand Down
1 change: 1 addition & 0 deletions src/wallet/constants/WalletName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export const WalletName = {
COSMOSTATION: "cosmostation",
METAMASK_INJECTIVE: "metamask-injective",
NINJI: "ninji",
OWALLET: "owallet",
} as const;
export type WalletName = (typeof WalletName)[keyof typeof WalletName];
3 changes: 2 additions & 1 deletion src/wallet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ export { KeplrController } from "./wallets/keplr/KeplrController";
export { LeapController } from "./wallets/leap/LeapController";
export { MetamaskInjectiveController } from "./wallets/metamask-injective/MetamaskInjectiveController";
export { MnemonicWallet } from "./wallets/mnemonic/MnemonicWallet";
export { StationController } from "./wallets/station/StationController";
export { NinjiController } from "./wallets/ninji/NinjiController";
export { OWalletController } from "./wallets/owallet/OWalletController";
export { StationController } from "./wallets/station/StationController";
78 changes: 78 additions & 0 deletions src/wallet/wallets/owallet/OWalletController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Secp256k1PubKey } from "cosmes/client";

import { WalletName } from "../../constants/WalletName";
import { WalletType } from "../../constants/WalletType";
import { onWindowEvent } from "../../utils/window";
import { WalletConnectV1 } from "../../walletconnect/WalletConnectV1";
import { WalletConnectV2 } from "../../walletconnect/WalletConnectV2";
import { ConnectedWallet } from "../ConnectedWallet";
import { ChainInfo, WalletController } from "../WalletController";
import { OWalletExtension } from "./OWalletExtension";

export class OWalletController extends WalletController {
constructor() {
super(WalletName.OWALLET);
this.registerAccountChangeHandlers();
}

public async isInstalled(type: WalletType) {
return type === WalletType.EXTENSION ? "owallet" in window : false;
}

protected async connectWalletConnect<T extends string>(
_chains: ChainInfo<T>[]
): Promise<{
wallets: Map<T, ConnectedWallet>;
wc: WalletConnectV1 | WalletConnectV2;
}> {
// OWallet does not support WC yet
throw new Error("WalletConnect not supported");
}

protected async connectExtension<T extends string>(chains: ChainInfo<T>[]) {
const wallets = new Map<T, ConnectedWallet>();
const ext = window.owallet;
if (!ext) {
throw new Error("OWallet extension is not installed");
}
await ext.enable(chains.map(({ chainId }) => chainId));
for (const { chainId, rpc, gasPrice } of Object.values(chains)) {
const { bech32Address, pubKey, isNanoLedger } = await ext.getKey(chainId);
const key = new Secp256k1PubKey({
chainId,
key: pubKey,
});
wallets.set(
chainId,
new OWalletExtension(
this.id,
ext,
chainId,
key,
bech32Address,
rpc,
gasPrice,
isNanoLedger
)
);
}
return wallets;
}

protected registerAccountChangeHandlers() {
/**
* ! IMPORTANT !
*
* Since Keplr also uses the same event key, this causes issues when a user
* has both Keplr and OWallet wallets connected simultaneously. For example,
* a change in Keplr's keystore will trigger OWallet to emit this event as
* well, leading to a race condition when `changeAccount` is called.
*
* The OWallet team has been notified to possibly change this event emitted
* to `owallet_keystorechange` instead.
*/
onWindowEvent("keplr_keystorechange", () =>
this.changeAccount(WalletType.EXTENSION)
);
}
}
4 changes: 4 additions & 0 deletions src/wallet/wallets/owallet/OWalletExtension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { KeplrExtension } from "../keplr/KeplrExtension";

// OWallet's API is similar to Keplr.
export const OWalletExtension = KeplrExtension;
10 changes: 10 additions & 0 deletions src/wallet/wallets/owallet/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Keplr } from "cosmes/registry";

// Type is similar to Keplr
export type OWallet = Keplr & {
isOwallet: true;
};

export type Window = {
owallet?: OWallet | undefined;
};
4 changes: 3 additions & 1 deletion src/wallet/wallets/window.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Window as CosmostationWindow } from "./cosmostation/types";
import { Window as LeapWindow } from "./leap/types";
import { Window as EthereumWindow } from "./metamask-injective/types";
import { Window as NinjiWindow } from "./ninji/types";
import { Window as OWalletWindow } from "./owallet/types";
import { Window as StationWindow } from "./station/types";

declare global {
Expand All @@ -15,5 +16,6 @@ declare global {
LeapWindow,
CompassWindow,
EthereumWindow,
NinjiWindow {}
NinjiWindow,
OWalletWindow {}
}

0 comments on commit 944db24

Please sign in to comment.