I am trying to interact with a smart contract method and getting the error -
ExecutionError: "Smart contract panicked: cannot read property 'prefix' of undefined\n" +
' at reconstruct (build/microsoft.js:994)\n' +
' at _reconstruct (build/microsoft.js:1102)\n' +
' at buy (build/microsoft.js:1137)\n'
Below is my smart contract :
import { NearBindgen, call, view, UnorderedMap, initialize } from 'near-sdk-js';
@NearBindgen({})
export class ExchangeContractMicrosoft {
private stocks: UnorderedMap<number> = new UnorderedMap<number>(
'unique-id-map1',
);
constructor() {
this.stocks.set('msft', 10000000);
}
@call({})
buy(): void {
const stock: string = 'msft';
this.checkStock(stock, 1);
this.stocks.set('msft', this.stocks.get(stock) - 1);
}
private checkStock(stock: string, value: number): void {
if (this.stocks.get(stock) < value) {
throw 'Not enough stocks';
}
}
}
I am trying to interact using :
near call sipars.testnet buy '{}' --accountId sipars.testnet --gas=300000000000000
Could someone help figure out what I am doing wrong ?
This most likely happens because you have made changes to your smart-contract since the first time you deployed it. You can then end up accessing an object that hasn't been defined yet. This can happen if you try to initialize additional objects after having deployed the contract once already.
For example
private stocks: UnorderedMap<number> = new UnorderedMap<number>('prefix1');
constructor() {
this.stocks.set('msft', 10);
}
@call({})
buy(): number {
const stock: string = 'msft';
return this.stocks.get(stock); // will return 10
}
private stocks: UnorderedMap<number> = new UnorderedMap<number>('prefix1');
private superStocks: UnorderedMap<number> = new UnorderedMap<number>('prefix2'); // will not be initialized when we re-deploy the contract
constructor() {
this.stocks.set('msft', 10);
this.superStocks.set('msft', 20); // this will never be called if we re-deploy to the same address
}
@call({})
buy(): number {
const stock: string = 'msft';
return this.superStocks.get(stock); // Opps. Cannot read property 'prefix' of undefined\n
}
A smart-contract that is already deployed will not call the constructor again if you re-deploy it (on the same address.) The constructor is only called on the first deploy.
If I take your current smart-contract code, build and deploy it, I'm able to call the buy
function without getting an error.
The only way I was able to fix the issue was to deploy the contract to a new address. According to this GitHub comment, adding a new field to the existing contract require a migration, so this is not a bug.