#Error: @method decorator was applied to [object Object], which is not a function. at method (/pa

1 messages · Page 1 of 1 (latest)

rancid plover
#

I'm deploying a Mina zkApp server-side using o1js and encountering this error:
Error: @method decorator was applied to [object Object], which is not a function.
at method (/path/to/zkapp.ts:118:11)
...
Here's my setup:

  1. Game Contract Code:

import { SmartContract, method, state, State, PublicKey, UInt64 } from 'o1js';

export class GameContract extends SmartContract {
@state(PublicKey) player1 = State<PublicKey>();
@state(PublicKey) player2 = State<PublicKey>();
@state(UInt64) totalAmount = State<UInt64>();

@method async initGame(player1Address: PublicKey, player2Address: PublicKey) {
this.player1.set(player1Address);
this.player2.set(player2Address);
this.send({ to: this.address, amount: UInt64.from(1_000_000_000) });
}
.....
}
2. Contract Deployment (Server-Side):

import { PrivateKey, PublicKey, UInt64, Mina, AccountUpdate } from "o1js";
import { GameContract } from "../../contracts/src/Game";

async function deployGameContract(
deployerKey: PrivateKey,
players: PublicKey[]
): Promise<{ zkAppAddress: string; txId: string }> {
const zkAppPrivateKey = PrivateKey.random();
const zkAppAddress = zkAppPrivateKey.toPublicKey();
const zkAppInstance = new GameContract(zkAppAddress);

const Network = Mina.Network("https://api.minascan.io/node/devnet/v1/graphql");
Mina.setActiveInstance(Network);

const deployTransaction = await Mina.transaction(
{
sender: deployerKey.toPublicKey(),
fee: UInt64.from(1_000_000),
},
async () => {
AccountUpdate.fundNewAccount(deployerKey.toPublicKey());
zkAppInstance.deploy(); // Deploy zkApp
zkAppInstance.initGame(players[0], players[1]);
}
);

...
}

Additional Information:

This code is executed server-side.
Node version: 22.3.0.
Could the issue be due to my TypeScript setup or Node version compatibility with o1js? Any guidance would be appreciated!

kind hound
#

use await

await zkAppInstance.deploy();
await zkAppInstance.initGame(players[0], players[1]);
lone blaze
#

Make sure that your tsconfig.json has

"experimentalDecorators": true, // needed for decorators
"emitDecoratorMetadata": true, // needed for decorators
"useDefineForClassFields": false, // ensure correct behaviour of class fields with decorators
rancid plover
#

I added both suggestions above into the code and i unfortunately still have the same problem.

  1. Smart COntract
    import { SmartContract, method, state, State, PublicKey, UInt64 } from 'o1js';

export class GameContract extends SmartContract {
@state(PublicKey) player1 = State<PublicKey>();
@state(PublicKey) player2 = State<PublicKey>();
@state(UInt64) totalAmount = State<UInt64>();

@method async initGame(player1Address: PublicKey, player2Address: PublicKey) {
this.player1.set(player1Address);
this.player2.set(player2Address);

this.send({ to: this.address, amount: UInt64.from(1_000_000_000) });

}

@method async distributeReward(winnerAddress: PublicKey) {
const p1 = this.player1.get();
const p2 = this.player2.get();

const isWinnerValid = winnerAddress.equals(p1).or(winnerAddress.equals(p2));
isWinnerValid.assertTrue('Winner must be one of the two players');

this.send({ to: winnerAddress, amount: UInt64.from(2_000_000_000) });

}
}

#
  1. Deploy Contract function in server side

import { PrivateKey, PublicKey, UInt64, Mina, AccountUpdate } from "o1js";
import { GameContract } from "../../contracts/src/Game";

/**

  • Helper function to deploy the GameContract smart contract
  • @param {PrivateKey} deployerKey - The private key for the deployer account
  • @param {PublicKey[]} players - Array of public keys for players (2 players)
  • @returns {Promise<{ zkAppAddress: string; txId: string }>} - Returns the zkApp address and transaction ID
    */
    async function deployGameContract(
    deployerKey: PrivateKey,
    players: PublicKey[]
    ): Promise<{ zkAppAddress: string; txId: string }> {
    const zkAppPrivateKey = PrivateKey.random();
    const zkAppAddress = zkAppPrivateKey.toPublicKey();
    const zkAppInstance = new GameContract(zkAppAddress);

const Network = Mina.Network(
"https://api.minascan.io/node/devnet/v1/graphql"
);
Mina.setActiveInstance(Network);

const deployTransaction = await Mina.transaction(
{
sender: deployerKey.toPublicKey(),
fee: UInt64.from(1_000_000),
},
async () => {
AccountUpdate.fundNewAccount(deployerKey.toPublicKey());
await zkAppInstance.deploy();
await zkAppInstance.initGame(players[0], players[1]);
}
);

await deployTransaction.sign([deployerKey, zkAppPrivateKey]);
const pendingTransaction = await deployTransaction.send();
const txId = pendingTransaction.hash;

return { zkAppAddress: zkAppAddress.toBase58(), txId };
}

export { deployGameContract };

#
  1. tsconfig in server side
    {
    "compilerOptions": {
    "outDir": "./dist",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "target": "ES2020",
    "strict": true,
    "esModuleInterop": true,
    "allowJs": true,
    "resolveJsonModule": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "useDefineForClassFields": false
    },
    "include": ["**/*.ts"],
    "exclude": ["node_modules", "dist"]
    }
marsh parrot
#

Can you share your package.json?

lone blaze
#

I've tried to run your code inside my next.js project, and it works (with some corrections).
You can check my configuration at
https://github.com/zkcloudworker/minatokens-ui/blob/main/next.config.mjs
https://github.com/zkcloudworker/minatokens-ui/blob/main/tsconfig.json
see the corrected code at
https://github.com/zkcloudworker/minatokens-ui/blob/main/src/pages/api/v1/test1.ts#L40
and run it today (I will disable the endpoint tomorrow) by

curl -X POST \
  -H "Content-Type: application/json" \
  https://minatokens.com/api/v1/test1

that gives

{"zkAppAddress":"B62qk35LU5nT86MBYB79SCt7qG1jUKAWynMXiV1sMDKpL3ue3KpPi63","txId":"5JuGhbQr5WpYG2emRzVGipzJEPiK57Jrkgmy1nmnMfUi9oXhBusP"}

and tx on devnet
https://minascan.io/devnet/tx/5JuGhbQr5WpYG2emRzVGipzJEPiK57Jrkgmy1nmnMfUi9oXhBusP?type=zk-tx

rancid plover
# marsh parrot Can you share your package.json?

Sure, the package json for serverside is as below
{
"type": "module",
"main": "index.js",
"scripts": {
"prebuild": "rm -rf dist",
"dev": "nodemon --exec tsx index.ts",
"build": "tsc",
"start": "node dist/index.js"
},
"dependencies": {
"@types/express": "^5.0.0",
"@types/node": "^22.9.0",
"@types/socket.io": "^3.0.2",
"express": "^4.21.1",
"o1js": "^2.0.0",
"socket.io": "^4.8.1"
},
"devDependencies": {
"nodemon": "^3.1.7",
"tsx": "^4.19.2",
"@types/express": "^4.17.15",
"@types/node": "^20.16.5"
}
}

rancid plover
lone blaze
#

Do you intend to run the server 24/7 instead of using "use server" functions? You will need the server with 8GB of RAM for proving to work that should be restarted a few times a day to run o1js proving reliably

rancid plover
#

I dont understand what you meant above. I am new to SmartContracts.
I have been thinking to make a multiplayer game with socket io and the server will run 24/7.
Additionally, i wanted to initilise the contract in the serverSide. So will this require 8gb ram useage?

lone blaze
rancid plover
#

I am using express for my server. So i think i will not be limited by memory constraints.

#

My main problem for the time being, the code throws this error below when i run the server.

/Mina/zkApp-tileGame/contracts/node_modules/o1js/src/lib/mina/zkapp.ts:118
throw Error(
^

Error: @method decorator was applied to [object Object], which is not a function.
at method (/Mina/zkApp-tileGame/contracts/node_modules/o1js/src/lib/mina/zkapp.ts:118:11)
at __decorateElement (f/Mina/zkApp-tileGame/contracts/src/Game.ts:1:2161)
at <anonymous> (/Mina/zkApp-tileGame/contracts/src/Game.ts:16:11)
at ModuleJob.run (node:internal/modules/esm/module_job:262:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:474:24)
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:109:5)

#

I updated the tsconfig.json but it seems it didnt help

marsh parrot
#

I've managed to build server with the tsconfig.json below

{
  "compilerOptions": {
    "outDir": "./dist",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "target": "ES2020",
    "strict": true,
    "esModuleInterop": true,
    "allowJs": true,
    "resolveJsonModule": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "useDefineForClassFields": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "declaration": true,
    "skipLibCheck": true
  },
  "include": ["**/*.ts"],
  "exclude": ["node_modules", "dist"]
}
lone blaze
ashen kite
#

I'm outdoors right now but will check your issue in a few hours @rancid plover

rancid plover
#

Many thanks 🙏

marsh parrot
rancid plover
#

no, it didn't unfortunately

rancid plover
# lone blaze You can also start your zkApp from the existing template https://github.com/DeMo...

Since I am new to zkApps, I am not sure but it seems the approach in this repo is not the same.
I think smart contract is already deployed and zkAppAddress is being passed to the Context Provider in the client side as below.
<QuestContractProvider
zkappPublicKey={PublicKey.fromBase58(
"B62qjDnppFhY5tsEmLbCDRniCoJcYqLmHpEeXVfwM4Ej18uJFhTrmBb"
)}
>
But what i want is to deploy the contract in the server side and pass the zkappPublicKey to client side. and I recieve the error I mentioned before.

lone blaze
# rancid plover Since I am new to zkApps, I am not sure but it seems the approach in this repo i...

You already have three working examples of how to handle SmartContract code.

You can take any of those examples as the template for your code, or you can work on your repo by changing the configuration in the package.json and tsconfig.json to make it work, using the info from the examples.

If you want to do this, you first need to put in order your package.json, which now uses incompatible versions of the same packages in the different parts of the package.json.

ashen kite
rancid plover
#

I encountered issues integrating SmartContract deployment within the Express.js setup due to unresolved tsconfig and package.json configuration errors. After searching for solutions without success, I reluctantly moved the deployment logic to Next.js's API folder, where the initial errors no longer appear. However, I'm now facing the following error:

"- You are missing an 'await' somewhere, which causes a new global context to be entered before we finished the last one.

You are importing two different instances of o1js, which leads to inconsistent tracking of the global context in one of those instances.

This is a common problem in projects that use o1js as part of a UI!

You are running multiple async operations concurrently, which conflict in using the global context.

Running async o1js operations (like proving) in parallel is not supported! Try running everything serially."

I will need to investigate further to address this issue.

For the multiplayer game I am planning, the phase 1 use case involves:

  1. Two users logging into the game.
  2. Deploying a smart contract on the server side, with the zkAppAddress sent to the client (a new smart contract is deployed for each game).
  3. Using ZKProgram to prove each move.
  4. Sending relevant game-end information to the smart contract.

It seems I may have missed some details in the SmartContract deployment process, so I plan to review additional repositories and documentation to resolve these challenges.

https://github.com/SerkanToraman/zkApp-tileMatch

GitHub

Contribute to SerkanToraman/zkApp-tileMatch development by creating an account on GitHub.