Cannot read property 'prefix' of undefined Error when call smart contract
- neuneuOP 1
I’m building an E platform project where users can purchase in NEAR using React and typescript. I get that error when I click to confirm the transaction:
Sorry an error has occurred. You may want to try again. {"index":0,"kind":{"ExecutionError":"Smart contract panicked: cannot read property 'prefix' of undefined\n at reconstruct (build/hello_near.js:1017)\n at _reconstruct (build/hello_near.js:1131)\n at purchaseBasket (build/hello_near.js:1207)\n"}},The smart contract is written in typescript:
import { NearBindgen, near, call, view, UnorderedMap, initialize } from 'near-sdk-js'; @NearBindgen({}) class MyContract { beneficiary: string = "mywallet.testnet"; orders = new UnorderedMap<Order[]>("orders"); @initialize({ privateFunction: true }) init({ beneficiary }: { beneficiary: string }) { this.beneficiary = beneficiary } @call({payableFunction: true}) purchaseBasket({basket, totalPrice}: {basket: OrderItem[]; totalPrice: number}) { near.log(basket, totalPrice); // Get who is paying let sender = near.predecessorAccountId(); let donationAmount: bigint = near.attachedDeposit() as bigint; near.log(sender, donationAmount); // Send NEAR token to the beneficiary const promise = near.promiseBatchCreate(this.beneficiary) near.promiseBatchActionTransfer(promise, donationAmount); // Update sender orders let currentOrders = this.orders.get(sender, {defaultValue: []}) || []; near.log(currentOrders); currentOrders.push({ items: basket, totalPrice: totalPrice, timestamp: near.blockTimestamp() }); near.log(currentOrders); this.orders.set(sender, currentOrders); near.log(this.orders); } @view({}) getOrders({accountId}: {accountId: string}): Order[] { let ordersList = this.orders.get(accountId, {defaultValue: []}); return ordersList; } } class OrderItem { id: string; name: string; priceInDollar: number; url: string; quantity: number; } class Order { items: OrderItem[]; totalPrice: number; timestamp: bigint; }Note that none of the near.log() log anything in the web inspector.
And this is where the call method is called:import React, {useState, useEffect} from 'react'; import {addToBasket, removeFromBasket, removeItemFromBasket, resetBasket} from '../app/basketSlice.js'; import {useSelector, useDispatch} from 'react-redux'; import Container from 'react-bootstrap/Container'; import Button from 'react-bootstrap/Button'; import Card from 'react-bootstrap/Card'; import Spinner from 'react-bootstrap/Spinner'; import {Img} from 'react-image'; import '../assets/global.css'; import {utils} from 'near-api-js'; export const Basket = ({isSignedIn, contractId, wallet}) => { const [nearToDollar, setNearToDollar] = useState(0); const basket = useSelector(state => state.items); const total = useSelector(state => state.totalPrice); const dispatch = useDispatch(); useEffect(() => { const getNearToDollar = async() => { let data = await fetch("https://api.coingecko.com/api/v3/simple/price?ids=near&vs_currencies=usd").then(response => response.json()) const near2usd = data['near']['usd'] const amount_in_near = 1 / near2usd const rounded_two_decimals = Math.round(amount_in_near * 100) / 100; setNearToDollar(rounded_two_decimals); } getNearToDollar(); }, []); const handleOrder = async() => { const amountInNear = total*nearToDollar; let deposit = utils.format.parseNearAmount(amountInNear.toString()); return await wallet.callMethod({ contractId: contractId, method: 'purchaseBasket', args: { basket: basket, totalPrice: total }, deposit }) } const connect = () => {wallet.signIn()} const handleResetBasket = () => { dispatch(resetBasket()); } const handleAddToBasket = (item) => { dispatch(addToBasket(item)); } const handleRemoveFromBasket = (item) => { dispatch(removeFromBasket(item)); } const handleRemoveItem = item => { dispatch(removeItemFromBasket(item)); } return ( <Container> <div className='mt-5 mb-5 d-flex justify-content-between'> <h1>Your Basket</h1> <Button onClick={handleResetBasket}>Reset Basket</Button> </div> <Container className='d-flex flex-wrap justify-content-center'> {basket.map((item, index) => { return ( <Card className='d-flex flex-column m-2' key={index} style={{ width: '18rem' }}> <Img className='m-1' variant="top" src={item.url} loader={<Spinner animation="border" role="status"></Spinner>}/> <Card.Body className='d-flex flex-column justify-content-end'> <Card.Title className='d-flex justify-content-between'> <div>{item.name}</div> <div>{item.quantity}</div> </Card.Title> <Card.Text> $ {item.priceInDollar*item.quantity} = {item.priceInDollar*nearToDollar*item.quantity} Ⓝ </Card.Text> <div className='d-flex justify-content-between'> <Button className='rounded-button' variant='secondary' onClick={() => handleAddToBasket(item)}>+</Button> <Button className='rounded-button' variant='secondary' onClick={() => handleRemoveFromBasket(item)}>-</Button> <Button variant="danger" onClick={() => handleRemoveItem(item)}>Remove</Button> </div> </Card.Body> </Card> ) })} </Container> <h3>Total: $ {total} = {nearToDollar*total} Ⓝ </h3> {isSignedIn? ( <Button onClick={handleOrder}>Buy</Button> ) : ( <Button onClick={connect}>Connect Wallet</Button> )} </Container> ) }Do you have any idea what I’m doing wrong?
Thanks. - chi.ha 2
- bailey12 2
Sorry for the late reply, here are some potential issues that could cause bugs for the first snippet:
- The
OrderItemandOrderclasses are not imported, so they may cause issues if they are not defined elsewhere in the code. - The
beneficiaryvariable is hard-coded to"mywallet.testnet". It is not clear whether this is the intended behavior or whether it should be set dynamically. - The
getOrdersfunction does not have a decorator for its arguments. It is possible that this may cause issues with the function’s behavior. - The
near.attachedDeposit()function returns a string, but it is being cast to abigint. This may cause issues if the attached deposit is not a validbigint. - The
promiseBatchCreatefunction is being called with a single argument. According to thenear-sdk-jsdocumentation, this function takes two arguments: a list of actions and an optional transaction metadata object. - The
promiseBatchActionTransferfunction is being called with a single argument. According to thenear-sdk-jsdocumentation, this function takes three arguments: a batch promise, the recipient account ID, and the transfer amount.
For the second snippet:
- The
basket,total, andisSignedInprops are assumed to be defined, but there is no check for their existence before using them. This could lead to runtime errors if they are not provided. - The
handleOrderfunction assumes that thewalletobject is defined and has acallMethodmethod. It might be a good idea to add a check for the existence of these before calling the method. - The
handleAddToBasket,handleRemoveFromBasket, andhandleRemoveItemfunctions assume that thedispatchfunction is defined. It might be a good idea to add a check for the existence ofdispatchbefore using it. - The
Imgcomponent from thereact-imagelibrary is used without a fallbacksrcattribute. This means that if the image fails to load, there will be no alternative displayed. It might be a good idea to add asrcattribute with a placeholder image URL or a fallback component to handle errors.
Try to double check all of these and if it is still not working, pls follow @chi.ha 's suggestion
- The
- neuneu 1
Hi, thanks for your response both.
Yes my smart contract can certainly be written better but I don’t think there was any error.
I couldn’t explain why but I removed mybuild/,neardev/andnode_modules/folders, then runnpm installandnpm run deployand it was all working fine…