Problem with coin exchange transaction not being broadcast

I'm trying to use the ardor API to do coin exchange transaction. I have no problem doing transaction on any chain, when the exchange==1. Problem appears when I tried to do transaction on exchange!=1.

I fill the field:
chain, exchange, quantityQNT, priceNQTPerCoin, and secretPhrase.

When then click on "submit", the transaction is broadcast if exchange==1, but not if exchange!=1. I see "broadcasted": false
in the response if exchange!=1.

I would like to broadcast the transaction, but appears it does not. What I am missing.

Thank you for help. I'm on 2.3.3.

Could you please try to reproduce it on testnet with a test account?

Then you can paste here the exact request and response received so we can diagnose what the problem is.

Thanks.

Thanks for the response. Could you send me some testnet Ardr to ARDOR-8Q58-G88J-K5PQ-2ACY5 on 2.3.3? Public key is be94b7c0552abf4ec028dbd75ed8f092b2f93f332870b4f71c04d634e6595e58

TY

You can use the testnet faucets for both Ardor and Ignis from Ardor.world: https://www.ardor.world/en/

Here is an example of what do not work for me:
I filled the following:
image

This is the request:
{
"info": {
"name": "exchangeCoins.1609706831781",
"schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json"
},
"item": [
{
"name": "exchangeCoins",
"request": {
"url": {
"raw": "http://localhost:26876/nxt?requestType=exchangeCoins",
"protocol": "http",
"host": [
"localhost"
],
"port": "26876",
"path": [
"nxt"
],
"query": [
{
"key": "requestType",
"value": "exchangeCoins",
"equals": true,
"description": ""
}
],
"variable": []
},
"method": "POST",
"body": {
"mode": "urlencoded",
"urlencoded": [
{
"key": "requestType",
"value": "exchangeCoins"
},
{
"key": "chain",
"value": "4"
},
{
"key": "exchange",
"value": "6"
},
{
"key": "quantityQNT",
"value": "1000"
},
{
"key": "priceNQTPerCoin",
"value": "1000"
},
{
"key": "secretPhrase",
"value": ""
}
]
},
"description": ""
},
"response": []
}
]
}

This is the response:
{
"minimumFeeFQT": "1000000",
"signatureHash": "afcb44411f57865dbeba8fcbf314280462bba1ca28b543f1a7e024da19359a0a",
"transactionJSON": {
"senderPublicKey": "be94b7c0552abf4ec028dbd75ed8f092b2f93f332870b4f71c04d634e6595e58",
"chain": 4,
"signature": "9440e90fdf640d99e216bd07d198d940ad164a2a43fd7cf93a72e16e8fe03b0d54b94f33b7cd56684bbed5c857f426f00d04276b56270eb8d99f79e109fcf1e4",
"feeNQT": "4000000",
"type": 11,
"fullHash": "25d8e41eeff0904cccac99f2175903d570c55ff91f87173e0dabf539f7fe2a4f",
"version": 1,
"fxtTransaction": "0",
"phased": false,
"ecBlockId": "8328295121127143691",
"signatureHash": "afcb44411f57865dbeba8fcbf314280462bba1ca28b543f1a7e024da19359a0a",
"attachment": {
"quantityQNT": "1000",
"chain": 4,
"priceNQTPerCoin": "1000",
"version.CoinExchangeOrderIssue": 1,
"exchangeChain": 6
},
"senderRS": "ARDOR-8Q58-G88J-K5PQ-2ACY5",
"subtype": 0,
"amountNQT": "0",
"sender": "142224515773192294",
"ecBlockHeight": 6446659,
"deadline": 15,
"timestamp": 95410032,
"height": 2147483647
},
"unsignedTransactionBytes": "040000000b000170d7af050f00be94b7c0552abf4ec028dbd75ed8f092b2f93f332870b4f71c04d634e6595e580000000000000000000000000000000000093d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000435e62000bf96697490c947300000000010400000006000000e803000000000000e803000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"broadcasted": false,
"requestProcessingTime": 1,
"transactionBytes": "040000000b000170d7af050f00be94b7c0552abf4ec028dbd75ed8f092b2f93f332870b4f71c04d634e6595e580000000000000000000000000000000000093d00000000009440e90fdf640d99e216bd07d198d940ad164a2a43fd7cf93a72e16e8fe03b0d54b94f33b7cd56684bbed5c857f426f00d04276b56270eb8d99f79e109fcf1e4435e62000bf96697490c947300000000010400000006000000e803000000000000e803000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"fullHash": "25d8e41eeff0904cccac99f2175903d570c55ff91f87173e0dabf539f7fe2a4f",
"bundlerRateNQTPerFXT": "400000000"
}

If you change chain from 4 to 1. The transaction is broadcasted.

You don't seem to be setting the fee for the transaction.

Try using the returned fee and add feeNQT=4000000

It does not work with the "supposed" automatic returned fee, ie I try with feeNQT=-1. The transaction is not broadcast.

If I put feeNQT=4000000 or 1000000. It does work.

Now my question would be why it work like this for chain!=1, but not chain=1?

Overall, the documentation would need to be update, as this was not very clear.

Thank you.

feeNQT=-1 is not supposed to broadcast the tx with any automatic calculation but to compute the best fee and return it as part of the transaction object.

About the difference on chain=1 keep in mind the first chain, or parent chain, has different fees. A coin exchange tx on the parent chain has a fixed fee of 0.5 ARDR. While a coin exchange between child chains costs the usual child chain fee of 0.01 ARDR.

Thank Sergi,

I now change a little the subject of the initial post.

I know the difference in fee between chain, the question is why do I need to provide the fee with chain!=1 and not with chain=1.

From my point of view, I think it could be useful if transaction would be broadcast automatically with minimal fee, only when those inputs are provided:
chain, exchange, quantityQNT, priceNQTPerCoin, and secretPhrase are provided.

This work with chain=1. Indeed, I do not need to provide any fee to the API and do not need to know the underlying fee.

As it stand right now, I need to provide an additional field 0.01 ARDR with chain!=1, but do not need to provide this field with chain=1.

Thus, the API is not uniform between chain.

One question I have is what is the reason to offer an API that is different between chain? Is it a bug, a feature not yet complete, or there is an underlying reason for this difference?

In any cases and whatever the reasons, as a suggestion for improvement, I think the documentation needs to be update as all this is not clear. The documentation provide clear instruction for chain=1, but not for chain!=1. Indeed, from my understanding, we do not need to know the underlying fee for chain=1 while for chain!=1, we need to know it, or retrieve it first then broadcast the transaction with the cst ARDR 0.01 fee.

Maybe there is something I miss in the documentation, but if I did not miss anything, I would not be here if documentation was a bit more clear on this subject.

Thank you.

The parent chain is indeed different from the other chains (child chains). This is on purpose and one of the basic foundations of the platform.

Blocks are only created on the parent chain. And those block only contain parent chain transactions. Transactions from any child chain must be packed into a special parent chain (child chain block). This process is called "bundling". More information:

About fees this is how it works in a nutshell. All fees on the platform are ultimately paid in ARDR on the parent chain. Those fees are fixed and hard-coded (https://ardordocs.jelurida.com/Faq#Ardor_Fee_Structures). Child chain transactions pay to the bundlers in the child chain token, then the bundler take the child chain transactions and create a child chain block parent transaction.

Given the way the bundling process works there is effectively a market for child chain fees. There can be multiple bundlers for each child chain. Each bundler announces it's rate, how many child chain tokens per ARDR charges for transactions. So you can have an IGNIS bundler with a rate 2 which means your bundler will accept 2 IGNIS per 1 ARDR when bundling transactions. This means a IGNIS payment that has a fixed fee of 0.01 ARDR will be bundled for 0.02 IGNIS.

So let me know try to address your specific questions:

I know the difference in fee between chain, the question is why do I need to provide the fee with chain!=1 and not with chain=1.
From my point of view, I think it could be useful if transaction would be broadcast automatically with minimal fee...

Because fees for chain=1 are fixed and known. That's not the case for the child chain. What if there is no bundler right now? What if there's only one bundler asking for 1 million IGNIS per ARDR? Would you like the wallet to automatically spend thousands of IGNIS on a simple transaction without your approval?

One question I have is what is the reason to offer an API that is different between chain? Is it a bug, a feature not yet complete, or there is an underlying reason for this difference?

As explained above there is indeed an architectural difference between the parent chain and the child chains.

Sergi thank you for your response.

OK. I was expecting this answer, but wanted to know if there was other reasons than that. From my point of view, I doubt this would happen with ignis chain, but maybe this could happen on child chain with lower usage. As a failsafe, I only keep small amount on account manage by "non human" to avoid exactly this. In that case, the server would return me an error (insufficient fund). Beside, I have my own bundler running to avoid such bad rate.

So case close onto why API is different from one chain to another. Now, let move onto to last subject so that everyone may benefit from.

Indeed, since API usage is different from one chain to another, could Jelurida please update documentation accordingly. There are no example for chain!=1, see:

Cancel Coin Exchange Example

Exchange Coins Example

on page

In my opinion, as well, the response from the server should be more clear. Indeed, no information on why the transaction was not broadcast was returned by the server. The server act as if everything was OK. Indeed, no error or warning about missing NECESSARY [not optional] field was responded by the server. Indeed, the field "feeNQT" seems to be necessary in this case with chain!=1, so if it is missing, I think the response from the server should tell us.

As a suggestion, in the case of a missing NECESSARY [not optional] input, could it be possible that the server respond to us which fields are necessary so that a transaction is broadcasted? I think it would obviously help future developers.

Can you confirm that the documentation or server response could be clearer? Or if this is the expected behavior and there is no intention to make improvement suggested above, I would like to know why.

Thank you Sergi.

Well, you could say that for a lot, if not all, APIs. Chain 1 is different from the rest. So general notes about API that create a transaction are put together here (https://ardordocs.jelurida.com/Create_Transaction#Create_Transaction_Request) where you can find details about the fee related parameters.

I admit that documentation could always be improved. I will propose that we should expand about how fees' parameters work on the API.

The current design doesn't actually require feeNQT, but it just works by computing the correct fee in case the parameter is missing. Changing a public API is something that should be done very careful to not break existing applications.

As an example the wallet uses this mechanism to first call the API without the fee and populating the proposed fee to the UI so the user can confirm the broadcasting of the transaction.

The answer to that would be always yes, of course.

1 Like