UNPKG

@broxus/js-core

Version:

MobX-based JavaScript Core library

377 lines (376 loc) 14.5 kB
"use strict"; 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); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TvmToken = void 0; const js_utils_1 = require("@broxus/js-utils"); const everscale_inpage_provider_1 = require("everscale-inpage-provider"); const mobx_1 = require("mobx"); const constants_1 = require("../../constants"); const core_1 = require("../../core"); const tvm_token_wallet_1 = require("../../models/tvm-token-wallet"); const TvmTokenUtils_1 = require("../../models/tvm-token/TvmTokenUtils"); const utils_1 = require("../../utils"); class TvmToken extends core_1.SmartContractModel { _connection; options; _provider; static Utils = TvmTokenUtils_1.TvmTokenUtils; static Wallet = tvm_token_wallet_1.TvmTokenWallet; /** * @template T * @param {ProviderRpcClient} _connection * Standalone RPC client that doesn't require connection to the TVM wallet provider * @param {TvmTokenCtorData['address'] | Readonly<T & TvmTokenCtorData>} data * TvmToken root address or an object of a token attributes (e.g. decimals, symbol, name) * @param {Readonly<GaugeAccountCtorOptions>} [options] * (optional) TvmToken Smart Contract Model options * @param {ProviderRpcClient} [_provider] * (optional) RPC provider that require connection to the TVM wallet */ constructor(_connection, data, options, _provider) { const isAddress = typeof data === 'string' || data instanceof everscale_inpage_provider_1.Address; if (!isAddress && !('address' in data)) { throw new Error('Address is not specified'); } const address = (0, utils_1.resolveTvmAddress)(isAddress ? data : data.address); super(_connection, address); this._connection = _connection; this.options = options; this._provider = _provider; if (isAddress) { this.setData(() => ({ address, tags: new Set(), })); } else if (data != null && typeof data === 'object' && !Array.isArray(data)) { this.setData(() => ({ ...data, address, tags: new Set(data.tags), })); } (0, mobx_1.makeObservable)(this); } /** * @template {TvmTokenCtorData | ObjectLiteral} V * @param {ProviderRpcClient} connection * Standalone RPC client that doesn't require connection to the TVM wallet provider * @param {TvmTokenCtorData['address'] | Readonly<V & TvmTokenCtorData>} data * TvmToken root address or an object of a token attributes (e.g. decimals, symbol, name) * @param {Readonly<TvmTokenCreateOptions>} [options] * (optional) TvmToken Smart Contract Model options * @param {ProviderRpcClient} [provider] * (optional) RPC provider that require connection to the TVM wallet */ static async create(connection, data, options, provider) { const { sync = true, watch, watchCallback, ...restOptions } = { ...options }; const token = new TvmToken(connection, data, restOptions, provider); if (sync) { await token.sync({ force: false, ttl: options?.ttl }); } if (watch) { await token.watch(watchCallback); } return token; } async sync(options) { if (!options?.force && this.isSyncing) { return; } try { this.setState('isSyncing', !options?.silent); const state = await this.syncContractState({ force: options?.force || !this.contractState, ttl: options?.ttl || constants_1.SECONDS_IN_HOUR * 1000, }); await this.syncComputedStorageData(); if (!this.isDeployed) { (0, js_utils_1.throwException)('Token is not deployed'); } const [details, burnByRootDisabled, burnPaused, mintDisabled] = await Promise.all([ TvmToken.Utils.getDetails(this._connection, this.address, state), TvmToken.Utils.burnByRootDisabled(this._connection, this.address, state), TvmToken.Utils.burnPaused(this._connection, this.address, state), TvmToken.Utils.mintDisabled(this._connection, this.address, state), ]); if (!details?.symbol || details.decimals == null) { (0, js_utils_1.throwException)('Token has invalid data and cannot be resolved'); } this.setData({ burnByRootDisabled, burnPaused, mintDisabled, ...details }); } catch (e) { if (process.env.NODE_ENV !== 'production') { const state = await this._connection.getProviderState(); (0, utils_1.syncErrorMessage)(this.constructor.name, this.address, e, state.networkId.toString()); } } finally { this.setState('isSyncing', false); } } async watch(callback) { try { this.contractSubscriber = new this._connection.Subscriber(); await this.contractSubscriber.states(this.address).delayed(stream => { if (process.env.NODE_ENV !== 'production') { (0, utils_1.subscribeDebugMessage)(this.constructor.name, this.address); } return stream.on((0, js_utils_1.debounce)(async (event) => { if (process.env.NODE_ENV !== 'production') { const state = await this._connection.getProviderState(); (0, utils_1.contractStateChangeDebugMessage)(this.constructor.name, this.address, event, state.networkId.toString()); } if ((0, utils_1.areAddressesEqual)(event.address, this.address)) { await this.sync({ force: !this.isSyncing, silent: true }); callback?.(...this.toJSON(true)); return; } await this.unwatch(); }, this.options?.watchDebounceDelay ?? 3000)); }); return this.contractSubscriber; } catch (e) { await this.unwatch(); throw e; } } async unwatch() { try { await this.contractSubscriber?.unsubscribe(); this.contractSubscriber = undefined; if (process.env.NODE_ENV !== 'production') { (0, utils_1.unsubscribeDebugMessage)(this.constructor.name, this.address); } } catch (e) { if (process.env.NODE_ENV !== 'production') { const state = await this._connection.getProviderState(); (0, utils_1.unsubscribeErrorMessage)(this.constructor.name, this.address, e, state.networkId.toString()); } } } async wallet(ownerAddress, options) { const address = await this.walletOf(ownerAddress); return TvmToken.Wallet.create(this._connection, { address }, options, this._provider); } async walletOf(ownerAddress) { return TvmToken.Utils.walletOf(this._connection, { ownerAddress, tokenAddress: this.address, }, this.contractState); } async balance(ownerAddress) { const walletAddress = await this.walletOf(ownerAddress); return TvmToken.Wallet.Utils.balance(this._connection, { walletAddress }); } /** * Returns token `address` as a string. * @returns {string} */ get root() { return this.address.toString(); } /** * Returns token `chainId`. Basically describes in the assets manifest. * @returns {TvmTokenData['chainId']} */ get chainId() { return this._data.chainId; } /** * Returns token `decimals`. Can be described in the assets manifest or * retrieved from a blockchain by a token address * (use **TvmToken.Utils.getDecimals(address)**). * @returns {TvmTokenData['decimals']} */ get decimals() { return this._data.decimals; } /** * Returns token `logoURI`. Basically describes in the assets manifest. * @returns {TvmTokenData['logoURI']} */ get icon() { return this._data.logoURI; } /** * Returns token `name`. Can be described in the assets manifest or * retrieved from a blockchain by a token address * (use **TvmToken.Utils.getName(address)**) * @returns {TvmTokenData['name']} */ get name() { return this._data.name; } /** * Returns token `symbol`. Can be described in the assets manifest or * retrieved from a blockchain by a token address * (use **TvmToken.Utils.getSymbol(address)**) * @returns {TvmTokenData['symbol']} */ get symbol() { return this._data.symbol; } /** * Returns token `rootOwnerAddress`. Can be described in the assets manifest or * retrieved from a blockchain by a token address * (use **TvmToken.Utils.rootOwnerAddress(address)**) * @returns {TvmTokenData['rootOwnerAddress']} */ get rootOwnerAddress() { return this._data.rootOwnerAddress; } /** * Returns token `totalSupply`. Can be described in the assets manifest or * retrieved from a blockchain by a token address * (use **TvmToken.Utils.totalSupply(address)**) * @returns {TvmTokenData['totalSupply']} */ get totalSupply() { return this._data.totalSupply; } /** * Returns token `vendor` as organization slug. Basically describes in the assets manifest. * @returns {TvmTokenData['vendor']} */ get vendor() { return this._data.vendor; } /** * Returns token `verified` flag. Basically describes in the assets manifest. * @returns {TvmTokenData['verified']} */ get verified() { return this._data.verified; } get burnByRootDisabled() { return this._data.burnByRootDisabled; } get burnPaused() { return this._data.burnPaused; } get mintDisabled() { return this._data.mintDisabled; } get(key) { return this._data[key]; } /** * Returns copy of the current token */ clone() { return new TvmToken(this._connection, this.toJSON(), this.options, this._provider); } } exports.TvmToken = TvmToken; __decorate([ mobx_1.action.bound, __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], TvmToken.prototype, "sync", null); __decorate([ mobx_1.action.bound, __metadata("design:type", Function), __metadata("design:paramtypes", [Function]), __metadata("design:returntype", Promise) ], TvmToken.prototype, "watch", null); __decorate([ mobx_1.action.bound, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", Promise) ], TvmToken.prototype, "unwatch", null); __decorate([ mobx_1.action.bound, __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], TvmToken.prototype, "wallet", null); __decorate([ mobx_1.action.bound, __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], TvmToken.prototype, "walletOf", null); __decorate([ mobx_1.action.bound, __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], TvmToken.prototype, "balance", null); __decorate([ mobx_1.computed, __metadata("design:type", String), __metadata("design:paramtypes", []) ], TvmToken.prototype, "root", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "chainId", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "decimals", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "icon", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "name", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "symbol", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "rootOwnerAddress", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "totalSupply", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "vendor", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "verified", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "burnByRootDisabled", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "burnPaused", null); __decorate([ mobx_1.computed, __metadata("design:type", Object), __metadata("design:paramtypes", []) ], TvmToken.prototype, "mintDisabled", null);