Initialize TypeScript library for Telegram Web App wallet integration
- Added configuration files: .eslintrc.js, .gitignore, .npmrc, .prettierrc, and multiple tsconfig files for different module systems. - Created package.json with dependencies and scripts for building, testing, and publishing. - Implemented core functionality in src/ directory, including wallet management, encryption, and storage handling. - Added README.md for documentation on installation, usage, and development setup. - Introduced initial types and constants for better type safety and code organization.
This commit is contained in:
commit
a21ea39c36
19 files changed
+5094
No files matched your search
+140
@@ -0,0 +1,140 @@
|
||||
import type { InjectedMetadataKnown } from "@polkadot/extension-inject/types";
|
||||
import { VARAN_WALLET_LS_KEY } from "./constants";
|
||||
import { generateRequestId } from "./helpers";
|
||||
import { WalletStorage } from "./types";
|
||||
|
||||
type WalletStoreType = {
|
||||
accounts: string[];
|
||||
injectedMetadataKnown?: InjectedMetadataKnown;
|
||||
transactions: {
|
||||
id: number;
|
||||
signedTx: string;
|
||||
status: 'signing' | 'success' | 'failed';
|
||||
}[];
|
||||
}
|
||||
|
||||
const defaultStore: WalletStoreType = {
|
||||
accounts: [],
|
||||
injectedMetadataKnown: undefined,
|
||||
transactions: [],
|
||||
}
|
||||
|
||||
export class WalletStore {
|
||||
constructor(
|
||||
private readonly store: WalletStorage,
|
||||
) {
|
||||
this._setupListeners();
|
||||
}
|
||||
|
||||
private callbacks: {
|
||||
[K in keyof WalletStoreType]: ({
|
||||
cb: (value: WalletStoreType[K]) => void,
|
||||
id: number;
|
||||
})[];
|
||||
} = {
|
||||
accounts: [],
|
||||
injectedMetadataKnown: [],
|
||||
transactions: [],
|
||||
};
|
||||
|
||||
private get _store(): WalletStoreType {
|
||||
return JSON.parse(this.store.getItem(VARAN_WALLET_LS_KEY) || '{}') as WalletStoreType;
|
||||
}
|
||||
|
||||
private _setupListeners(): void {
|
||||
let currentState = this._store;
|
||||
this.store.subscribe(ev => {
|
||||
ev.stopImmediatePropagation();
|
||||
if (ev.key !== VARAN_WALLET_LS_KEY) return;
|
||||
|
||||
const data = JSON.parse(ev.newValue || '{}') as WalletStoreType;
|
||||
currentState = data;
|
||||
const keys = Object.keys(data) as (keyof WalletStoreType)[];
|
||||
for (const key of keys) {
|
||||
if (key === 'injectedMetadataKnown') continue;
|
||||
if (key === 'accounts') {
|
||||
const currentAccounts = currentState[key];
|
||||
const dataAccounts = data[key];
|
||||
if (currentAccounts.length !== dataAccounts.length) {
|
||||
this.dispatch(key);
|
||||
continue;
|
||||
}
|
||||
|
||||
let shouldDispatch = false;
|
||||
dataAccounts.forEach(account => {
|
||||
if (!currentAccounts.includes(account)) {
|
||||
shouldDispatch = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (shouldDispatch) {
|
||||
this.dispatch(key);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (key === 'transactions') {
|
||||
const currentTransactions = currentState[key];
|
||||
const dataTransactions = data[key];
|
||||
if (currentTransactions.length !== dataTransactions.length) {
|
||||
this.dispatch(key);
|
||||
continue;
|
||||
}
|
||||
|
||||
let shouldDispatch = false;
|
||||
dataTransactions.forEach(transaction => {
|
||||
if (!currentTransactions.find(t => t.id === transaction.id)) {
|
||||
shouldDispatch = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (shouldDispatch) {
|
||||
this.dispatch(key);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private dispatch<Key extends keyof WalletStoreType>(key: Key): void {
|
||||
const callbacks = this.callbacks[key];
|
||||
if (!callbacks || callbacks.length === 0) return;
|
||||
callbacks.forEach(c => c.cb(this._store[key]));
|
||||
}
|
||||
|
||||
get<Key extends keyof WalletStoreType>(key: Key): WalletStoreType[Key] {
|
||||
return this._store[key];
|
||||
}
|
||||
|
||||
set<Key extends keyof WalletStoreType>(key: Key, value: WalletStoreType[Key]): void {
|
||||
this._store[key] = value;
|
||||
this.store.setItem(VARAN_WALLET_LS_KEY, JSON.stringify(this._store));
|
||||
}
|
||||
|
||||
remove<Key extends keyof WalletStoreType>(key: Key): void {
|
||||
const value = this._store[key];
|
||||
if (value) {
|
||||
this._store[key] = defaultStore[key];
|
||||
}
|
||||
this.store.setItem(VARAN_WALLET_LS_KEY, JSON.stringify(this._store));
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.store.removeItem(VARAN_WALLET_LS_KEY);
|
||||
}
|
||||
|
||||
subscribe<Key extends keyof WalletStoreType>(key: Key, cb: (value: WalletStoreType[Key]) => void): number {
|
||||
if (this.callbacks[key] == undefined) {
|
||||
this.callbacks[key] = [];
|
||||
}
|
||||
const id = generateRequestId();
|
||||
this.callbacks[key].push({cb, id});
|
||||
return id;
|
||||
}
|
||||
|
||||
unsubscribe<Key extends keyof WalletStoreType>(key: Key, id: number): void {
|
||||
if (this.callbacks[key] == undefined || this.callbacks[key].length === 0) return;
|
||||
const filtered = this.callbacks[key].filter(c => c.id !== id);
|
||||
this.callbacks[key] = filtered as typeof this.callbacks[Key];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user