Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Keplr offline signer, minimize interface #117

Merged
merged 3 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/big-eggs-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@babylonlabs-io/bbn-wallet-connect": patch
---

Keplr offline signer, minimize interface
25 changes: 16 additions & 9 deletions src/core/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { SigningStargateClient, SigningStargateClientOptions } from "@cosmjs/stargate";
import { ChainInfo } from "@keplr-wallet/types";
import { ChainInfo, OfflineAminoSigner, OfflineDirectSigner } from "@keplr-wallet/types";
import { ComponentType } from "react";

export type Fees = {
Expand Down Expand Up @@ -257,15 +256,23 @@ export interface IBBNProvider extends IProvider {
getPublicKeyHex(): Promise<string>;

/**
* Gets the signing stargate client.
* @returns A promise that resolves to the signing stargate client.
* Gets the name of the wallet provider.
* @returns A promise that resolves to the name of the wallet provider.
*/
getSigningStargateClient(options?: SigningStargateClientOptions): Promise<SigningStargateClient>;
getWalletProviderName(): Promise<string>;

/**
* Gets the balance of the connected wallet.
* @param searchDenom - The denomination to search for in the wallet's balance.
* @returns A promise that resolves to the balance of the connected wallet.
* Gets the icon URL of the wallet provider.
* @returns A promise that resolves to the icon URL of the wallet provider.
*/
getWalletProviderIcon(): Promise<string>;

getBalance(searchDenom: string): Promise<bigint>;
/**
* Retrieves an offline signer that supports both Amino and Direct signing methods.
* This signer is used for signing transactions offline before broadcasting them to the network.
*
* @returns {Promise<OfflineAminoSigner & OfflineDirectSigner>} A promise that resolves to a signer supporting both Amino and Direct signing
* @throws {Error} If wallet connection is not established or signer cannot be retrieved
*/
getOfflineSigner(): Promise<OfflineAminoSigner & OfflineDirectSigner>;
}
25 changes: 17 additions & 8 deletions src/core/wallets/bbn/BBNProvider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { SigningStargateClient, SigningStargateClientOptions } from "@cosmjs/stargate";
import { OfflineAminoSigner, OfflineDirectSigner } from "@keplr-wallet/types";

import { IBBNProvider } from "@/core/types";

Expand All @@ -23,14 +23,23 @@ export abstract class BBNProvider implements IBBNProvider {
abstract getPublicKeyHex(): Promise<string>;

/**
* Gets the signing stargate client.
* @returns A promise that resolves to the signing stargate client.
* Gets the name of the wallet provider.
* @returns A promise that resolves to the name of the wallet provider.
*/
abstract getSigningStargateClient(options?: SigningStargateClientOptions): Promise<SigningStargateClient>;
abstract getWalletProviderName(): Promise<string>;

/**
* Gets the icon URL of the wallet provider.
* @returns A promise that resolves to the icon URL of the wallet provider.
*/
abstract getWalletProviderIcon(): Promise<string>;

/**
* Gets the balance of the connected wallet.
* @param searchDenom - The denomination to search for in the wallet's balance.
* @returns A promise that resolves to the balance of the connected wallet.
* Retrieves an offline signer that supports both Amino and Direct signing methods.
* This signer is used for signing transactions offline before broadcasting them to the network.
*
* @returns {Promise<OfflineAminoSigner & OfflineDirectSigner>} A promise that resolves to a signer supporting both Amino and Direct signing
* @throws {Error} If wallet connection is not established or signer cannot be retrieved
*/
abstract getBalance(searchDenom: string): Promise<bigint>;
abstract getOfflineSigner(): Promise<OfflineAminoSigner & OfflineDirectSigner>;
}
32 changes: 15 additions & 17 deletions src/core/wallets/bbn/keplr/provider.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { SigningStargateClient, SigningStargateClientOptions } from "@cosmjs/stargate";
import { Window as KeplrWindow } from "@keplr-wallet/types";
import { OfflineAminoSigner, OfflineDirectSigner } from "@keplr-wallet/types/src/cosmjs";
import { Buffer } from "buffer";

import { BBNConfig, WalletInfo } from "@/core/types";
import { BBNProvider } from "@/core/wallets/bbn/BBNProvider";

import logo from "./logo.svg";

declare global {
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface Window extends KeplrWindow {}
Expand All @@ -15,8 +16,6 @@ export class KeplrProvider extends BBNProvider {
private walletInfo: WalletInfo | undefined;
private chainId: string | undefined;
private rpc: string | undefined;
private offlineSigner?: OfflineAminoSigner & OfflineDirectSigner;
private stargateClient?: Promise<SigningStargateClient>;
private chainData: BBNConfig["chainData"];

constructor(
Expand Down Expand Up @@ -62,8 +61,6 @@ export class KeplrProvider extends BBNProvider {

if (!key) throw new Error("Failed to get Keplr key");

this.offlineSigner = this.keplr.getOfflineSigner(this.chainId);

const { bech32Address, pubKey } = key;

if (bech32Address && pubKey) {
Expand All @@ -86,21 +83,22 @@ export class KeplrProvider extends BBNProvider {
return this.walletInfo.publicKeyHex;
}

async getSigningStargateClient(options?: SigningStargateClientOptions) {
if (!this.stargateClient) {
this.stargateClient = this.createSigningStargateClient(options);
}
return await this.stargateClient;
async getWalletProviderName(): Promise<string> {
return "Keplr";
}

async createSigningStargateClient(options?: SigningStargateClientOptions) {
if (!this.rpc) throw new Error("RPC URL is not initialized");
if (!this.offlineSigner) throw new Error("Offline signer is not initialized");
return await SigningStargateClient.connectWithSigner(this.rpc, this.offlineSigner, options);
async getWalletProviderIcon(): Promise<string> {
return logo;
}

async getBalance(searchDenom: string) {
const signingStargateClient = await this.getSigningStargateClient();
return BigInt((await signingStargateClient.getBalance(await this.getAddress(), searchDenom)).amount);
async getOfflineSigner(): Promise<OfflineAminoSigner & OfflineDirectSigner> {
if (!this.keplr) throw new Error("Keplr extension not found");
if (!this.chainId) throw new Error("Chain ID is not initialized");

try {
return this.keplr.getOfflineSigner(this.chainId);
} catch {
throw new Error("Failed to get offline signer");
}
}
}