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:
odiinnn committed 2025-08-28 13:13:57 +03:00
commit a21ea39c36
19 files changed
+5094

No files matched your search

+140
View File
@@ -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];
}
}