REST API endpoint for verifying transactions on mainnet and testnet using transaction hash

Hey Guys
Greetings!
Quick question: Does anyone know if there’s a REST API we can use to verify transactions on the Concordium blockchain by their transaction hash? I found this endpoint: https://wallet-proxy.testnet.concordium.com/v0/submissionStatus/${txnHash}, but I’m facing a couple of issues:

  1. When we pass additional data as a hexstring during transaction initiation, it seems to add some extra characters, messing up our decoding process.
  2. Also, this endpoint is only for the testnet, but we need something that works for the mainnet too.

Any ideas on how we can tackle this? Thanks!

Do you need a REST API?

grpc.testnet.concordium.com and grpc.mainnet.concordium.software are publicly provided endpoints where you can query transaction statuses/outcomes. They are meant to be used programmatically. The wallet-proxy is not.

We have a number of SDKs that make it very simple to query these statuses, both from a browser context or from other applications. See SDKs and APIs — Concordium documentation

I strongly recommend using one of those. Would that work for you?

Building this as we speak on Concordium Explorer. What other endpoints would be helpful to have?

It currently lives as a dev api on https://dev-api.concordium-explorer.nl/v1/mainnet/transaction/hash

Hey @abizjak,

Could you help me locate the endpoints on grpc.testnet.concordium.com and grpc.mainnet.concordium.software that allow querying for a transaction using the transaction hash? Simply visiting these sites doesn’t seem to lead me to any relevant documentation.

Also, regarding the Concordium documentation link you provided earlier, I’ve checked out the transactions section, but couldn’t find a method for retrieving transaction details using a transaction hash.

Appreciate your assistance in pointing me in the right direction!

@sderuiter this is niceee! only issue is that the parameter property which is supposed to have the data I’m sending as hexstring seems to append some additional characters to the hexstring I sent, thereby messing the decoding process on my end.
Here is an image of data property when signing the contract (notice it starts with 7b and ends with 7d)

Here is the hexstring returned in the parameter property from the endpoint

you would notice there are additional characters - “010000c0843d00e15891347cc368764723c6248b78a8fb4c173ad54038a36e461a9639dd2d9acd008a3d892b84f72d6b113b88e593b93605596f2472ecd76bab53f8cb281d7f71109100” being added to the initial data I assed. please any idea whats causing this and how I can fix it?

Hmm, I’m reading this directly from the GRPC v2 spec as account_transaction, as in: there is no step where I add additional data to this particular field. Do you know how view the transaction in the block using Concordium-client? I can’t look right now, but I’m sure this reports the same info as the api does.

Also, are you sure you want the tx hash and not the logged events (looking at the tx type)?

Further to this comment, below is the output from Concordium-client for this specific transaction:


It’s showing the message field in the same way.

@sderuiter thanks for your help so far, I was able to use getBlockItemStatus and it also returns the message the same way. Been trying to figure out why it adds the extra bytes “010000c0843d00e15891347cc368764723c6248b78a8fb4c173ad54038a36e461a9639dd2d9acd008a3d892b84f72d6b113b88e593b93605596f2472ecd76bab53f8cb281d7f71109100”, haven’t figured it out so far. currently looking through Concordium docs and Github to see if there is any util that helps extract just the initial hex string I sent to the contract

Why do you say those are extra bytes?

In the screenshot of the wallet you have the full payload which consists of

  • token id
  • amount
  • sender
  • receiver
  • and some extra payload

Is it that you only want to extract this “data”, the extra payload?

Are you using Javascript/Typescript, Rust, .NET or Java for your parsing/querying?

We can describe how to get the data you want if you share what setup you are using.

@abizjak we are using Js/Ts setup. yes I only wan to extract “data”, the extra payload

For this parsing you would use a schema to extract the relevant data using the web-sdk.

    const contractName = ContractName.fromStringUnchecked('euroe_stablecoin_v3');
    const functionName = EntrypointName.fromStringUnchecked('transfer');
    const schema = 
        getUpdateContractParameterSchema(
            fullSchema,
            contractName,
            functionName,
            schemaVersion
        );
    const parsed = deserializeTypeValue(toBuffer(parameter), schema);
    // then parsed["data"] will be your "data" field if all goes well

@abizjak please how do I get fullSchema & schemaVersion

also not sure while the amount from Concordium-client shows 0, when I actually sent 1 Euroe

The amount is the amount of CCD you transferred to the contract. Which is 0 in this case.

The amount of EURe that was transferred is encoded inside the “message”.

The fullSchema you would get from the contract, using the getEmbeddedModuleSchema function.

You can get the module using the getModuleSource function from the chain.

@abizjak thanks for all your help so far. I can see the getModuleSource(ref, blockHash) takes two parameters, the ModuleReference and the blockHash. The blockHash I’m able to get when I call getBlockItemStatus. Please how can I get the module reference (ref). I can see from Concordium example of Github, they are doing something like this

const ref = ModuleReference.fromHexString(moduleRef);

my challenge now is how to get moduleRef which I guess would be a byte value (Buffer)

You can get it, for example, by querying getInstanceInfo of the contract address you want to inspect.

There is a sourceModule property which the reference you want.

@abizjak here is my setup so far, everything works untill it gets to getUpdateContractParameterSchema, then it logs an error "Unable to get parameter schema, due to: Parse error". Please any clue what the issue could be

    const blockItem = await grpcClient.getBlockItemStatus(TransactionHash.fromHexString(txHash))
    const instanceInfo = await grpcClient.getInstanceInfo(
      CONTRACT_ADDRESS, // ContractAddress.create(7260)
      blockItem.blockHash
    );
    const ref = ModuleReference.fromHexString(instanceInfo.sourceModule.moduleRef)

    const versionedSource = await grpcClient.getModuleSource(ref, blockItem.blockHash);
    const fullSchema = await getEmbeddedModuleSchema(versionedSource)
    console.log(fullSchema, "fullschema")

    const contractName = ContractName.fromStringUnchecked('euroe_stablecoin_v3');
    const functionName = EntrypointName.fromStringUnchecked('transfer');
    const schemaVersion = SchemaVersion.V1;
    const schema = getUpdateContractParameterSchema(
        fullSchema,
        contractName,
        functionName,
        schemaVersion
      );

Hi there

Almost there, you need to use the underlying buffer so fullSchema.buffer, also the schema version is only needed for older smart contracts, so you should be able to omit that part.

    const schema = getUpdateContractParameterSchema(
        fullSchema.buffer,
        contractName,
        functionName,
      );

Edit: I realized that you want to parse the parameter, which is currently not supported by ccd-js-gen, so side note below does not apply.

On a side note:
If you only care about a specific smart contracts such as the EUROe, then consider using @concordium/ccd-js-gen to generate a typescript client for the smart contract, which generates code hiding a lot of this.

1 Like