ton-core / ton

Most popular TON Typescript Library
MIT License
66 stars 49 forks source link

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

Open d0rich opened 10 months ago

d0rich commented 10 months ago

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 commented 10 months ago

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 ```js "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 }); } }; } ```