Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue.js TypeError: Cannot read private member from an object whose class did not declare it #26

Open
d0rich opened this issue Nov 25, 2023 · 1 comment

Comments

@d0rich
Copy link

d0rich commented Nov 25, 2023

I'm getting following error, when I am using get methods in the contracts in Vue.js app:

Uncaught (in promise) TypeError: Cannot read private member from an object whose class did not declare it
    at __classPrivateFieldGet (TonClient.js:17:94)
    at Proxy.runMethod (TonClient.js:53:25)
    at Proxy.callGetMethod (TonClient.js:68:21)
    at Object.get (TonClient.js:329:39)
    at DSocialNetworkMaster.getGetBlogsCount (tact_DSocialNetworkMaster.ts:1750:38)
    at Proxy.<anonymous> (openContract.js:38:47)
    at getLastBlogAddress (CreateBlog.vue:87:52)
    at goToNewBlogAddress (CreateBlog.vue:72:25)
    at callWithErrorHandling (runtime-core.esm-bundler.js:158:18)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:166:17)

Possibly, it also can be the case in other frameworks, but as far as I know Vue and JS private hash fields (TonClient.#api) have difficult relationships because of Proxies used by Vue. It might resolve the error, if we replace all hash fields with just private TS properties.

@d0rich
Copy link
Author

d0rich commented Nov 25, 2023

Update: Yep, I have tried to replace private hash methods outputs with public ones in the package, and problem was resolved.

Please, delete private hash fields from classes. I also can do that for you.

Changed JS file
"use strict";
/**
 * Copyright (c) Whales Corp.
 * All Rights Reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
var _TonClient_api;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TonClient = void 0;
const HttpApi_1 = require("./api/HttpApi");
const ton_core_1 = require("@ton/core");
class TonClient {
    constructor(parameters) {
        this.parameters = {
            endpoint: parameters.endpoint
        };
        this.api = new HttpApi_1.HttpApi(this.parameters.endpoint, {
          timeout: parameters.timeout,
          apiKey: parameters.apiKey,
          adapter: parameters.httpAdapter
        });
    }
    /**
     * Get Address Balance
     * @param address address for balance check
     * @returns balance
     */
    async getBalance(address) {
        return (await this.getContractState(address)).balance;
    }
    /**
     * Invoke get method
     * @param address contract address
     * @param name name of method
     * @param params optional parameters
     * @returns stack and gas_used field
     */
    async runMethod(address, name, stack = []) {
        let res = await this.api.callGetMethod(address, name, stack);
        if (res.exit_code !== 0) {
            throw Error('Unable to execute get method. Got exit_code: ' + res.exit_code);
        }
        return { gas_used: res.gas_used, stack: parseStack(res.stack) };
    }
    /**
     * Invoke get method
     * @param address contract address
     * @param name name of method
     * @param params optional parameters
     * @returns stack and gas_used field
     * @deprecated use runMethod instead
     */
    async callGetMethod(address, name, stack = []) {
        return this.runMethod(address, name, stack);
    }
    /**
     * Invoke get method that returns error code instead of throwing error
     * @param address contract address
     * @param name name of method
     * @param params optional parameters
     * @returns stack and gas_used field
    */
    async runMethodWithError(address, name, params = []) {
        let res = await this.api.callGetMethod(address, name, params);
        return { gas_used: res.gas_used, stack: parseStack(res.stack), exit_code: res.exit_code };
    }
    /**
     * Invoke get method that returns error code instead of throwing error
     * @param address contract address
     * @param name name of method
     * @param params optional parameters
     * @returns stack and gas_used field
     * @deprecated use runMethodWithError instead
     */
    async callGetMethodWithError(address, name, stack = []) {
        return this.runMethodWithError(address, name, stack);
    }
    /**
     * Get transactions
     * @param address address
     */
    async getTransactions(address, opts) {
        // Fetch transactions
        let tx = await this.api.getTransactions(address, opts);
        let res = [];
        for (let r of tx) {
            res.push((0, ton_core_1.loadTransaction)(ton_core_1.Cell.fromBoc(Buffer.from(r.data, 'base64'))[0].beginParse()));
        }
        return res;
    }
    /**
     * Get transaction by it's id
     * @param address address
     * @param lt logical time
     * @param hash transaction hash
     * @returns transaction or null if not exist
     */
    async getTransaction(address, lt, hash) {
        let res = await this.api.getTransaction(address, lt, hash);
        if (res) {
            return (0, ton_core_1.loadTransaction)(ton_core_1.Cell.fromBoc(Buffer.from(res.data, 'base64'))[0].beginParse());
        }
        else {
            return null;
        }
    }
    /**
     * Fetch latest masterchain info
     * @returns masterchain info
     */
    async getMasterchainInfo() {
        let r = await this.api.getMasterchainInfo();
        return {
            workchain: r.init.workchain,
            shard: r.last.shard,
            initSeqno: r.init.seqno,
            latestSeqno: r.last.seqno
        };
    }
    /**
     * Fetch latest workchain shards
     * @param seqno masterchain seqno
     */
    async getWorkchainShards(seqno) {
        let r = await this.api.getShards(seqno);
        return r.map((m) => ({
            workchain: m.workchain,
            shard: m.shard,
            seqno: m.seqno
        }));
    }
    /**
     * Fetch transactions inf shards
     * @param workchain
     * @param seqno
     * @param shard
     */
    async getShardTransactions(workchain, seqno, shard) {
        let tx = await this.api.getBlockTransactions(workchain, seqno, shard);
        if (tx.incomplete) {
            throw Error('Unsupported');
        }
        return tx.transactions.map((v) => ({
            account: ton_core_1.Address.parseRaw(v.account),
            lt: v.lt,
            hash: v.hash
        }));
    }
    /**
     * Send message to a network
     * @param src source message
     */
    async sendMessage(src) {
        const boc = (0, ton_core_1.beginCell)()
            .store((0, ton_core_1.storeMessage)(src))
            .endCell()
            .toBoc();
        await this.api.sendBoc(boc);
    }
    /**
     * Send file to a network
     * @param src source file
     */
    async sendFile(src) {
        await this.api.sendBoc(src);
    }
    /**
     * Estimate fees for external message
     * @param address target address
     * @returns
     */
    async estimateExternalMessageFee(address, args) {
        return await this.api.estimateFee(address, { body: args.body, initCode: args.initCode, initData: args.initData, ignoreSignature: args.ignoreSignature });
    }
    /**
     * Send external message to contract
     * @param contract contract to send message
     * @param src message body
     */
    async sendExternalMessage(contract, src) {
        if (await this.isContractDeployed(contract.address) || !contract.init) {
            const message = (0, ton_core_1.external)({
                to: contract.address,
                body: src
            });
            await this.sendMessage(message);
        }
        else {
            const message = (0, ton_core_1.external)({
                to: contract.address,
                init: { code: contract.init.code, data: contract.init.data },
                body: src
            });
            await this.sendMessage(message);
        }
    }
    /**
     * Check if contract is deployed
     * @param address addres to check
     * @returns true if contract is in active state
     */
    async isContractDeployed(address) {
        return (await this.getContractState(address)).state === 'active';
    }
    /**
     * Resolves contract state
     * @param address contract address
     */
    async getContractState(address) {
        let info = await this.api.getAddressInformation(address);
        let balance = BigInt(info.balance);
        let state = info.state;
        return {
            balance,
            state,
            code: info.code !== '' ? Buffer.from(info.code, 'base64') : null,
            data: info.data !== '' ? Buffer.from(info.data, 'base64') : null,
            lastTransaction: info.last_transaction_id.lt !== '0' ? {
                lt: info.last_transaction_id.lt,
                hash: info.last_transaction_id.hash,
            } : null,
            blockId: {
                workchain: info.block_id.workchain,
                shard: info.block_id.shard,
                seqno: info.block_id.seqno
            },
            timestampt: info.sync_utime
        };
    }
    /**
     * Open contract
     * @param src source contract
     * @returns contract
     */
    open(src) {
        return (0, ton_core_1.openContract)(src, (args) => createProvider(this, args.address, args.init));
    }
    /**
     * Create a provider
     * @param address address
     * @param init optional init
     * @returns provider
     */
    provider(address, init) {
        return createProvider(this, address, init);
    }
}
exports.TonClient = TonClient;
_TonClient_api = new WeakMap();
function parseStack(src) {
    let stack = [];
    for (let s of src) {
        if (s[0] === 'num') {
            let val = s[1];
            if (val.startsWith('-')) {
                stack.push({ type: 'int', value: -BigInt(val.slice(1)) });
            }
            else {
                stack.push({ type: 'int', value: BigInt(val) });
            }
        }
        else if (s[0] === 'null') {
            stack.push({ type: 'null' });
        }
        else if (s[0] === 'cell') {
            stack.push({ type: 'cell', cell: ton_core_1.Cell.fromBoc(Buffer.from(s[1].bytes, 'base64'))[0] });
        }
        else if (s[0] === 'slice') {
            stack.push({ type: 'slice', cell: ton_core_1.Cell.fromBoc(Buffer.from(s[1].bytes, 'base64'))[0] });
        }
        else if (s[0] === 'builder') {
            stack.push({ type: 'builder', cell: ton_core_1.Cell.fromBoc(Buffer.from(s[1].bytes, 'base64'))[0] });
        }
        else {
            throw Error('Unsupported stack item type: ' + s[0]);
        }
    }
    return new ton_core_1.TupleReader(stack);
}
function createProvider(client, address, init) {
    return {
        async getState() {
            let state = await client.getContractState(address);
            let balance = state.balance;
            let last = state.lastTransaction ? { lt: BigInt(state.lastTransaction.lt), hash: Buffer.from(state.lastTransaction.hash, 'base64') } : null;
            let storage;
            if (state.state === 'active') {
                storage = {
                    type: 'active',
                    code: state.code ? state.code : null,
                    data: state.data ? state.data : null,
                };
            }
            else if (state.state === 'uninitialized') {
                storage = {
                    type: 'uninit',
                };
            }
            else if (state.state === 'frozen') {
                storage = {
                    type: 'frozen',
                    stateHash: Buffer.alloc(0),
                };
            }
            else {
                throw Error('Unsupported state');
            }
            return {
                balance,
                last,
                state: storage,
            };
        },
        async get(name, args) {
            let method = await client.callGetMethod(address, name, args);
            return { stack: method.stack };
        },
        async external(message) {
            //
            // Resolve init
            //
            let neededInit = null;
            if (init && !await client.isContractDeployed(address)) {
                neededInit = init;
            }
            //
            // Send package
            //
            const ext = (0, ton_core_1.external)({
                to: address,
                init: neededInit ? { code: neededInit.code, data: neededInit.data } : null,
                body: message
            });
            let boc = (0, ton_core_1.beginCell)()
                .store((0, ton_core_1.storeMessage)(ext))
                .endCell()
                .toBoc();
            await client.sendFile(boc);
        },
        async internal(via, message) {
            // Resolve init
            let neededInit = null;
            if (init && (!await client.isContractDeployed(address))) {
                neededInit = init;
            }
            // Resolve bounce
            let bounce = true;
            if (message.bounce !== null && message.bounce !== undefined) {
                bounce = message.bounce;
            }
            // Resolve value
            let value;
            if (typeof message.value === 'string') {
                value = (0, ton_core_1.toNano)(message.value);
            }
            else {
                value = message.value;
            }
            // Resolve body
            let body = null;
            if (typeof message.body === 'string') {
                body = (0, ton_core_1.comment)(message.body);
            }
            else if (message.body) {
                body = message.body;
            }
            // Send internal message
            await via.send({
                to: address,
                value,
                bounce,
                sendMode: message.sendMode,
                init: neededInit,
                body
            });
        }
    };
}

d0rich added a commit to d0rich/esprit that referenced this issue Nov 26, 2023
d0rich added a commit to d0rich/esprit that referenced this issue Nov 26, 2023
d0rich added a commit to d0rich/esprit that referenced this issue Mar 5, 2024
* Update environment and metadata

* Delete template files

* Update package.json scripts

* Update build and prepare scripts

* Add TonConnect component to Home page

* Add wallet functionality to useTonConnect

* Move ton connections to Pinia store

* Add @esbuild-plugins/node-globals-polyfill
dependency

* Refactor TonConnectStore to use reactive
properties

* Header draft

* Fix theme switch and ton connect UI

* Syncronyze tonConnect theme with website theme

* Update colors in App.vue

* Layout draft

* Remove unused DBtn import in DFooter.vue

* lintfix

* Refactor TonConnectStore and DSidebar components

* Polyfill buffer in build

* Master contract store

* Make blogs NFT items

* Fix fees in test fixtures and contracts

* Refactor test setup in DSocialNetworkMaster and
DSocialNetworkBlog specs

* Fix create post fee validation and restrict post
creation to owner only

* Add transfer tests

* Group tests

* Rename contracts hooks and handle royalty params on transfer

* Optimize hooks

* Move contracts to packages

* Refactor masterContractStore to use dynamic master
contract addresses

* Refactor DPost

* Create markdown converters

* Remove unused import and update link in
DFooter.vue

* Create text for the main page

* Generate user avatar by wallet

* Update UserAvatar.vue to use thumbs collection

* Init sidebar navigation

* Create blog form

* useOpenedContract

* Replace deprecated ton packages

* Workaround for @ton/ton incompatibility with Vue

ton-core/ton#26

* Fix @ton/core patch

ton-core/ton#26

* Fix sidebar toggle in Layout.vue and DSidebar.vue

* Error: Unsupported item type: tvm.stackEntrySlice

* My blogs draft

* Add redirect rule to netlify.toml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant