Comment on page

Use your wallet where necessary

Here we will implement a class that loads a wallet and is able to do different operations on this wallet.
This class is not entirely necessary. There are other ways to achieve this but we made a class to have everything in one place. Also it allows you to modify some responses as you wish.
When the app starts you should create a WalletWrapper for each wallet the user has and save it in memory. A global map may be a good idea to be able to access the wallet from every component.
WalletWrapper.ts
import { Logger, LoggingLevel, Transaction, FeeRate } from "@peersyst/ckb-wallet-sdk";
import { loadWallet } from "./wallet-loader";
import { getTokenFromTokenAmount, CustomToken } from "./wallet-loader";
import { loadWalletInfo } from "./storage-service";
export class WalletWrapper {
private readonly wallet: WalletService;
private readonly mnemonic: string;
private readonly logger: Logger;
constructor(walletId: number, loggingLevel?: LoggingLevel) {
this.loadWalletInfowallet = loadWallet(walletId);
this.mnemonic = loadWalletInfo(walletId);
this.logger = new Logger(`${WalletWrapper.name}-${walletId}`, loggingLevel);
}
async synchronize(): Promise<void> {
try {
await this.wallet.synchronize();
} catch (error) {
this.logger.error(error.toString());
throw error;
}
}
getCKBBalance(): CKBBalance {
return this.wallet.getCKBBalance();
}
async getDAOBalance(): Promise<DAOBalance> {
try {
return this.wallet.getDAOBalance();
} catch (error) {
this.logger.error(error.toString());
throw error;
}
}
getTransactions(): Transaction[] {
return this.wallet.getTransactions();
}
async getTransaction(txHash: string): Promise<Transaction> {
try {
return this.wallet.getTransactionFromHash(txHash);
} catch (error) {
this.logger.error(error.toString());
throw error;
}
}
getTokensBalance(): CustomToken[] {
const tokens = this.wallet.getTokensBalance();
return tokens.map(getTokenFromTokenAmount);
}
getNfts(): Promise<Nft[]> {
try {
return this.wallet.getNftsBalance();
} catch (error) {
this.logger.error(error.toString());
throw error;
}
}
getAddress(): string {
return this.wallet.getNextAddress();
}
async sendTransaction(amount: bigint, to: string, feeRate: FeeRate): Promise<string> {
try {
return this.wallet.sendTransaction(amount, this.mnemonic, to, feeRate);
} catch (error) {
this.logger.error(error.toString());
throw error;
}
}
async depositInDAO(amount: bigint, feeRate: FeeRate): Promise<string> {
try {
return this.wallet.depositInDAO(amount, this.mnemonic, feeRate);
} catch (error) {
this.logger.error(error.toString());
throw error;
}
}
async getDAOUnlockableAmounts(): Promise<DAOUnlockableAmount[]> {
try {
return this.wallet.getDAOUnlockableAmounts();
} catch (error) {
this.logger.error(error.toString());
throw error;
}
}
async withdrawOrUnlock(unlockableAmount: UnlockableAmount): Promise<string> {
try {
return this.wallet.withdrawOrUnlock(unlockableAmount, this.mnemonic);
} catch (error) {
this.logger.error(error.toString());
throw error;
}
}
}
We save the mnemonic in the class to not ask it every time to the user. We could also have it protected with a pin.
On some cases we catch the errors. In these catches you could show something on screen to indicate the call failed.
Having a class allows to wrap functions such as getTokensBalance. This function checks the type of a token and maps it to something more understandable for the user..