@broxus/tvm-connect
Version:
TypeScript SDK for connecting to Nekoton-compatible wallets using a unified interface.
116 lines (115 loc) • 5.04 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { debounce, debug, error, isBrowser, throwException } from '@broxus/js-utils';
import { ProviderRpcClient, StaticProviderAdapter } from 'everscale-inpage-provider';
import { action, makeObservable, runInAction } from 'mobx';
import { NekotonConnector } from '../core';
import { ConnectionType, TvmProviderEvent, TvmWalletRdnsList, } from '../types';
export function venomProviderFallback(params) {
return (client) => new Promise((resolve, reject) => {
if (client) {
resolve(client);
return;
}
const fallbackAttempts = params?.fallbackAttempts ?? 5;
let attempts = 0;
const tryToResolve = debounce(() => {
if (attempts >= fallbackAttempts) {
reject(new Error(`Max attempts (${fallbackAttempts}) is reached.`));
return;
}
if (isBrowser() && window.__venom) {
debug('Venom Wallet provider was found with fallback', window.__venom);
resolve(window.__venom);
return;
}
attempts += 1;
tryToResolve();
}, 1000);
tryToResolve();
});
}
const rdnsList = [TvmWalletRdnsList.VENOM_WALLET.toString(), TvmWalletRdnsList.VENOM_WALLET_MOBILE.toString()];
export class VenomWallet extends NekotonConnector {
params;
type = ConnectionType.NEKOTON_WALLET;
constructor(params) {
super(params);
this.params = params;
makeObservable(this);
this.init().catch(error);
}
async init() {
let provider;
const onAnnouncement = async (event) => {
const { name, rdns } = event.detail.info;
if (name === 'Venom Wallet' || (rdns && rdnsList.includes(rdns))) {
window.removeEventListener(TvmProviderEvent.ANNOUNCE_PROVIDER, onAnnouncement);
provider = new ProviderRpcClient({
provider: new StaticProviderAdapter(event.detail.provider),
});
debug('Venom Wallet provider event was captured', event);
}
};
try {
this.setState('isInitializing', true);
if (isBrowser()) {
window.addEventListener(TvmProviderEvent.ANNOUNCE_PROVIDER, onAnnouncement);
window.dispatchEvent(new Event(TvmProviderEvent.REQUEST_PROVIDER));
}
if (!provider) {
if (this.params?.fallbackProviderFactory) {
provider = await this.params.fallbackProviderFactory();
}
else {
try {
const fallback = await venomProviderFallback({
fallbackAttempts: this.params?.fallbackAttempts,
})();
if (!fallback) {
throwException('No provider found');
}
provider = new ProviderRpcClient({ provider: fallback });
}
catch { }
}
}
const hasProvider = await provider?.hasProvider();
if (!hasProvider) {
throwException('No provider found');
}
if (isBrowser()) {
await provider?.ensureInitialized();
}
runInAction(() => {
this.provider = provider;
if (isBrowser()) {
window.removeEventListener(TvmProviderEvent.ANNOUNCE_PROVIDER, onAnnouncement);
}
});
if (this.params?.autoInit ?? true) {
await Promise.allSettled([this.preConnect(), this.runSubscriptions()]);
}
this.setState({ isInitialized: true, isInitializing: false });
}
catch (e) {
debug('Venom Wallet could not be initialized', e);
this.setState({ isInitialized: false, isInitializing: false });
await this.stopSubscriptions();
}
return this.provider;
}
}
__decorate([
action.bound,
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], VenomWallet.prototype, "init", null);