Calling nft methods from web

Hello,

I am using following tutorial Mint an NFT — Concordium documentation

I have the contract deployed and tested via cli. I am using following code to invoke the mint from frontend

async function testContractMinting() {
const client = createConcordiumClient(
node.testnet.concordium.com”,
Number(20000),
credentials.createInsecure()
);

const walletFile = readFileSync(“/home/yasir/concordium_dev/contracts/3SfHLNkmy61ZUQkAhMvAwKj47EYDBiUPbn3wHghFD6qGr8WDGc.export”, ‘utf8’);
const wallet = parseWallet(walletFile);
const sender = new AccountAddress(wallet.value.address);
const signer = buildAccountSigner(wallet);

const moduleRef = new ModuleReference(
‘97dc77b5de4c62a659aa31179e20f4968f25d0d1bb839d301b52a8a9f95b1ce7’
);
const maxCost = 30000n;
const contractName = ‘nft_review_2024-04-19’;
const receiveName = ‘nft_review_2024-04-19.mint’;
// const schema = await client.getEmbeddedSchema(moduleRef);

const rawModuleSchema = Buffer.from(readFileSync(
‘/home/yasir/concordium_dev/contracts/nft/nft-review/dist/cis2-nft/schema.bin’
));

const updateHeader: AccountTransactionHeader = {
expiry: new TransactionExpiry(new Date(Date.now() + 3600000)),
nonce: (await client.getNextAccountNonce(sender)).nonce,
sender,
};

const params = {
“owner”: {
“Account”: [“3SfHLNkmy61ZUQkAhMvAwKj47EYDBiUPbn3wHghFD6qGr8WDGc”]
},
“tokens”: [“00000003”]
};
// let params1 = “{ a:1 }”
// const params2 = Buffer.from(params);
const updateParams = serializeUpdateContractParameters(
contractName,
‘mint’,
params,
rawModuleSchema
);

// const inputParams = serializeInitContractParameters(
// contractName,
// params,
// rawModuleSchema,

// );

const updatePayload: UpdateContractPayload = {
amount: new CcdAmount(0n),
address: {“index”:BigInt(8665),“subindex”:BigInt(0)},
receiveName,
message: updateParams,
maxContractExecutionEnergy: maxCost,
};

const updateTransaction: AccountTransaction = {
header: updateHeader,
payload: updatePayload,
type: AccountTransactionType.Update,
};

const updateSignature = await signTransaction(updateTransaction, signer);
const updateTrxHash = await client.sendAccountTransaction(
updateTransaction,
updateSignature
);

console.log(‘Transaction submitted, waiting for finalization…’);

const updateStatus = await client.waitForTransactionFinalization(
updateTrxHash
);
console.dir(updateStatus, { depth: null, colors: true });
return updateStatus;

}

Express is listening at http://localhost:3000
string
/home/yasir/concordium_dev/dapps/test-contract-v2/node_modules/@protobuf-ts/grpc-transport/build/commonjs/grpc-transport.js:37
const e = new runtime_rpc_1.RpcError(err.details, grpc_js_1.status[err.code], util_1.metadataFromGrpc(err.metadata));
^

RpcError: Name resolution failed for target dns:node.testnet.concordium.com:20000
at Object.callback (/home/yasir/concordium_dev/dapps/test-contract-v2/node_modules/@protobuf-ts/grpc-transport/build/commonjs/grpc-transport.js:37:27)
at Object.onReceiveStatus (/home/yasir/concordium_dev/dapps/test-contract-v2/node_modules/@grpc/grpc-js/build/src/client.js:192:36)
at Object.onReceiveStatus (/home/yasir/concordium_dev/dapps/test-contract-v2/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:360:141)
at Object.onReceiveStatus (/home/yasir/concordium_dev/dapps/test-contract-v2/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:323:181)
at /home/yasir/concordium_dev/dapps/test-contract-v2/node_modules/@grpc/grpc-js/build/src/resolving-call.js:99:78
at process.processTicksAndRejections (node:internal/process/task_queues:77:11) {
code: ‘UNAVAILABLE’,
meta: {},
methodName: ‘GetNextAccountSequenceNumber’,
serviceName: ‘concordium.v2.Queries’
}

I don’t know why the name resolution error happens, the URL seems to be correct and should work fine for the connection.

It appears you use an old version of the SDK though. Could you try to use @concordium/web-sdk@latest instead? This is compatible with nodejs as well, and you can construct a GRPC client by:

import {ConcordiumGRPCNodeClient} from '@concordium/web-sdk/nodejs';
const client = new ConcordiumGRPCNodeClient(...);

You can see the documentation for this here: ConcordiumGRPCNodeClient | Concordium JS-SDK

Hope this helps.

Hello, I decided to use websdk CIS2-Contracts | Concordium JS-SDK

However, I get following error on code

const contractAddressT = {index: 1234n, subindex: 0n};
const contract = await CIS2Contract.create(client, contractAddressT);

Argument of type ‘{ index: bigint; subindex: bigint; }’ is not assignable to parameter of type ‘ContractAddress’.
Property ‘__type’ is missing in type ‘{ index: bigint; subindex: bigint; }’ but required in type ‘ContractAddress’.ts(2345)

How, should I modify the above statement?

The error comes because you likely use a newer version of the @concordium/web-sdk (version 7.0.0 or above).

The required change is e.g.:

const contractAddressT =  ContractAddress.create(1234n, 0n);

Here is a PR where we upgrade to use this newer web-sdk library in case you run into other conversion/upgrade errors in the types:

Thx, that works can i call mint using CIS2Contract?

The CIs2Client supports the entrypoints defined in the CIS-2-standard (this is updateOperator/transfer functions mainly and several read/view functions).

Mint function is not standardized so it can not be part of the general CIS2Client provided in the SDK. You can generate a Contract Client specific to your contract alternatively.

I get following error

   POST https://node.testnet.concordium.com:2000/concordium.v2.Queries/GetInstanceInfo net::ERR_CONNECTION_TIMED_OUT

Code

const address =‘https://node.testnet.concordium.com
const port = Number(2000)

// const [address, port] = parseEndpoint(cli.flags.endpoint);

const client = new ConcordiumGRPCWebClient(
address,
port,
{ timeout: 15000 }
);

The port number should be 20000 (one extra 0).

thx, i get this error now https://node.testnet.concordium.com:20000/concordium.v2.Queries/GetInstanceInfo net::ERR_SSL_PROTOCOL_ERROR

The connection is established in following

const client = new ConcordiumGRPCWebClient(
address,
port,
{ timeout: 15000 }
);
console.log(client)

but when I try to get tokenmeta by using following code, I get the error above

const contractAddressT = ContractAddress.create(xyzn, 0n);
const contract = await CIS2Contract.create(client, contractAddressT);

const tokenId = '00000002'; // HEX string representing a token ID defined in the contract.
const metadataUrl = await contract.tokenMetadata(tokenId);

SSL is not in use on that node, so you need to use ‘http://node.testnet.concordium.com’ as the address (i.e. httpshttp).

1 Like

The tokenmeta works, however, I am trying to transfer command as explained here

const {
type, // The transaction type.
payload, // The transaction payload
parameter: {
json, // The parameter to be supplied to the contract receive function in JSON format.
hex, // The parameter to be supplied to the contract receive function as a hex encoded string
},
schema: {
value, // The contract schema for the parameter. This is needed to translate the JSON format to a byte array.
type, // The type of the schema. This is always ‘parameter’, meaning it can be used for the JSON formatted parameter only.
}
} = contract.createTransfer(
{ energy: 10000n },
transfer
);

I get Cannot redeclare block-scoped variable ‘type’.ts(2451)