Returning `to` an `from` addresses from `Transactionid`

Hey all,

I would like to obtain the to & from addrsses for a particular TransactionId .

Running the GraphQL query below doesn’t have those fields populated. Is there another method for obtaining these fields ( to and from). Is there possibly a decoder for a raw tx, is the raw tx data obtainable from a TransactionId and is there a decoder? Or another method?

Query variable:
{“id”:“0xe5de0a5f248e1c5a156ee369d2996ecfcc794b3ca17b204c256d9b1d17a8c373”}

query($id: TransactionId!) {
  transaction(id: $id) {
    receipts {
      param1
      param2
      amount
      assetId
      gas
      digest
      contract {
        id
      }
      is
      pc
      ptr
      ra
      rb
      rc
      rd
      reason
      receiptType
      to {
        id
      }
      toAddress
      val
      len
      result
      gasUsed
      data
      sender
      recipient
      nonce
      contractId
      subId
    }
    status {
      __typename
      ... on SubmittedStatus {
        time
      }
      ... on SuccessStatus {
        block {
          id
        }
        time
        programState {
          returnType
          data
        }
      }
      ... on SqueezedOutStatus {
        reason
      }
      ... on FailureStatus {
        block {
          id
        }
        time
        reason
        programState {
          returnType
          data
        }
      }
    }
  }
}

Result:

{
  "data": {
    "transaction": {
      "receipts": [
        {
          "param1": null,
          "param2": null,
          "amount": null,
          "assetId": null,
          "gas": null,
          "digest": null,
          "contract": null,
          "is": "10344",
          "pc": "10344",
          "ptr": null,
          "ra": null,
          "rb": null,
          "rc": null,
          "rd": null,
          "reason": null,
          "receiptType": "RETURN",
          "to": null,
          "toAddress": null,
          "val": "1",
          "len": null,
          "result": null,
          "gasUsed": null,
          "data": null,
          "sender": null,
          "recipient": null,
          "nonce": null,
          "contractId": null,
          "subId": null
        },
        {
          "param1": null,
          "param2": null,
          "amount": null,
          "assetId": null,
          "gas": null,
          "digest": null,
          "contract": null,
          "is": null,
          "pc": null,
          "ptr": null,
          "ra": null,
          "rb": null,
          "rc": null,
          "rd": null,
          "reason": null,
          "receiptType": "SCRIPT_RESULT",
          "to": null,
          "toAddress": null,
          "val": null,
          "len": null,
          "result": "0",
          "gasUsed": "8872",
          "data": null,
          "sender": null,
          "recipient": null,
          "nonce": null,
          "contractId": null,
          "subId": null
        }
      ],
      "status": {
        "__typename": "SuccessStatus",
        "block": {
          "id": "0xaf369b45d2d209b1ff40a4fedbb5dc86eb23de8974897821c992cc0cf5c229bf"
        },
        "time": "4611686020129678765",
        "programState": {
          "returnType": "RETURN",
          "data": "0x0000000000000001"
        }
      }
    }
  }
}

Hey @Antony!

The GraphQL functionality of the indexer service needs a gigantic overhaul, as it doesn’t support variables, fragments, and other functionality that you’re trying to use in your query. Fortunately, I’ve been working on that very thing, and we should have it merged in the next week or two; you can monitor the progress at this PR.

As far as obtaining the information that you need, perhaps you can parse transaction receipts and see if you can find what you need there. You can also use the general testnet playground to see if the Fuel node provides any of the information that you need.

1 Like

Since asset transfers are native to fuel, the to and from fields are included in the UTXO inputs and outputs of the transaction for basic transfers and not the receipts. Receipts only apply to more advanced scripting and contract interactions, and there’s no reason to put these fields on the receipts for asset transfers since the information is already available on the transaction itself.

Using the GQL api on fuel-core, you can query for the exact fields like so:


{
  transaction(id:"0xdcb9c486e2ca125249306a0eedee219c4c55eae112c957aed12cace85481cf99") {
    inputs {
      ... on InputCoin {
        owner
      }
      ... on InputMessage {
        recipient
      }
      __typename
    }
    outputs {
      __typename
      ... on CoinOutput {
        to
      }
      ... on ChangeOutput {
        to
      }
      ... on VariableOutput {
        to
      }
    }
  }
}

Note: this is a transaction id from beta-4 I found in the block explorer.

You can try this curl command to see it for yourself:

curl 'https://beta-4.fuel.network/graphql' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Connection: keep-alive' -H 'DNT: 1' -H 'Origin: https://beta-4.fuel.network' --data-binary '{"query":"# Write your query or mutation here\n\n{\n  transaction(id:\"0xdcb9c486e2ca125249306a0eedee219c4c55eae112c957aed12cace85481cf99\") {\n    inputs {\n      ... on InputCoin {\n        owner\n      }\n      __typename\n    }\n    outputs {\n      __typename\n      ... on CoinOutput {\n        to\n      }\n      ... on ChangeOutput {\n        to\n      }\n      ... on VariableOutput {\n        to\n      }\n    }\n  }\n}"}' --compressed

Right, maybe I should specify this tx as a Script (predicate). however for a script tx one would have to iterate over all input UTXOs and all outputs UTXOs (in this case two inputs, - some input,and some change from previous tx) to find the from (owner) and all CoinOutput’s to find the to as (in this case one single output + a change) . Little bit cumbersome but sure, its gets messy for multi unique owners as inputs and potentially multi output to’s however. For this example ill just be using a single from and to.

The below is just a more verbose version of what you posted above.

setup:

Before:
--------------------------------------------------------
predAccount 	  :   Bech32Address { hrp: "fuel", hash: f0f5ddf97f6b5a74efa7877f37f092b38f6ba492abf76f1556941adc40b30e4a }
predAccount 	  : 0xf0f5ddf97f6b5a74efa7877f37f092b38f6ba492abf76f1556941adc40b30e4a
account balance:
asset_is: 0000000000000000000000000000000000000000000000000000000000000000
balance : 1821599993
feth    : 1.821599993


predAccount 	  :   Bech32Address { hrp: "fuel", hash: dd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a }
predAccount 	  : 0xdd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a
account balance:
asset_is: 0000000000000000000000000000000000000000000000000000000000000000
balance : 17289511095
feth    : 17.289511095

--------------------------------------------------------

After:
predAccount 	  :   Bech32Address { hrp: "fuel", hash: f0f5ddf97f6b5a74efa7877f37f092b38f6ba492abf76f1556941adc40b30e4a }
predAccount 	  : 0xf0f5ddf97f6b5a74efa7877f37f092b38f6ba492abf76f1556941adc40b30e4a
account balance:
asset_is: 0000000000000000000000000000000000000000000000000000000000000000
balance : 13021599993
feth    : 13.021599993

predAccount 	  :   Bech32Address { hrp: "fuel", hash: dd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a }
predAccount 	  : 0xdd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a
account balance:
asset_is: 0000000000000000000000000000000000000000000000000000000000000000
balance : 6089511094
feth    : 6.089511094

--------------------------------------------------------

Transaction:
0x64f770e3418db5f21ed39b8eaf9dee55f56790ce601cae45ebc5fdf8203d82e8

(on a local testnet)

Query:

query($id: TransactionId!) {
  transaction(id: $id) {
    gasLimit
    gasPrice
    id
    txPointer
    inputAssetIds
    inputContracts {
      id
    }
    inputs {
      __typename
      ... on InputCoin {
        utxoId
        owner
        amount
        assetId
        txPointer
        witnessIndex
        maturity
        predicateGasUsed
        predicateData
      }
      ... on InputContract {
        utxoId
        balanceRoot
        stateRoot
        txPointer
        contract {
          id
        }
      }
      ... on InputMessage {
        sender
        recipient
        amount
        nonce
        witnessIndex
        predicateGasUsed
        data
        predicate
        predicateData
      }
    }
    isScript
    isCreate
    isMint
    outputs {
      __typename
      ... on CoinOutput {
        to
        amount
        assetId
      }
      ... on ContractOutput {
        inputIndex
        balanceRoot
        stateRoot
      }
      ... on ChangeOutput {
        to
        amount
        assetId
      }
      ... on VariableOutput {
        to
        amount
        assetId
      }
      ... on ContractCreated {
        contract {
          id
        }
        stateRoot
      }
    }
    maturity
    receiptsRoot
    status {
      __typename
      ... on SubmittedStatus {
        time
      }
      ... on SuccessStatus {
        block {
          id
        }
        time
        programState {
          returnType
          data
        }
      }
      ... on SqueezedOutStatus {
        reason
      }
      ... on FailureStatus {
        block {
          id
        }
        time
        reason
        programState {
          returnType
          data
        }
      }
    }
    witnesses
    receipts {
      param1
      param2
      amount
      assetId
      gas
      digest
      contract {
        id
      }
      is
      pc
      ptr
      ra
      rb
      rc
      rd
      reason
      receiptType
      to {
        id
      }
      toAddress
      val
      len
      result
      gasUsed
      data
      sender
      recipient
      nonce
      contractId
      subId
    }
    script
    scriptData
    salt
    storageSlots
    bytecodeWitnessIndex
    bytecodeLength
  }
}

Result:

{
  "data": {
    "transaction": {
      "gasLimit": "1000000",
      "gasPrice": "1",
      "id": "0x64f770e3418db5f21ed39b8eaf9dee55f56790ce601cae45ebc5fdf8203d82e8",
      "txPointer": null,
      "inputAssetIds": [
        "0x0000000000000000000000000000000000000000000000000000000000000000",
        "0x0000000000000000000000000000000000000000000000000000000000000000"
      ],
      "inputContracts": [],
      "inputs": [
        {
          "__typename": "InputCoin",
          "utxoId": "0xe5a18811e6f6949ef0382c802c062626009ebdf22b0529d912f90910ee833bd900",
          "owner": "0xdd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a",
          "amount": "17100000000",
          "assetId": "0x0000000000000000000000000000000000000000000000000000000000000000",
          "txPointer": "000000000000",
          "witnessIndex": 0,
          "maturity": "0",
          "predicateGasUsed": "4436",
          "predicateData": "0x0000000000005d180000000000000080000000000000007a02f87783097bc80c85011bd4e67985011bd4e679827b0c94a778171c591f364748ae7fcea772881dbf3dcf08889b6e64a8ec60000080c001a08c40e52a7bc91972fa9b8f26e4a37d6e4a7a959227b27ef0c13493136be36cc1a03f831a53642a6505b74bea04615d607a25441f1525e71dd21ff21fb582cd99e5000000000000"
        },
        {
          "__typename": "InputCoin",
          "utxoId": "0x5b5f5a482511719efa0d871b3640f5c9519a8a42ff5120d8c136532312249ca501",
          "owner": "0xdd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a",
          "amount": "189511095",
          "assetId": "0x0000000000000000000000000000000000000000000000000000000000000000",
          "txPointer": "000000000000",
          "witnessIndex": 0,
          "maturity": "0",
          "predicateGasUsed": "4436",
          "predicateData": "0x00000000000092480000000000000080000000000000007a02f87783097bc80c85011bd4e67985011bd4e679827b0c94a778171c591f364748ae7fcea772881dbf3dcf08889b6e64a8ec60000080c001a08c40e52a7bc91972fa9b8f26e4a37d6e4a7a959227b27ef0c13493136be36cc1a03f831a53642a6505b74bea04615d607a25441f1525e71dd21ff21fb582cd99e5000000000000"
        }
      ],
      "isScript": true,
      "isCreate": false,
      "isMint": false,
      "outputs": [
        {
          "__typename": "CoinOutput",
          "to": "0xf0f5ddf97f6b5a74efa7877f37f092b38f6ba492abf76f1556941adc40b30e4a",
          "amount": "11200000000",
          "assetId": "0x0000000000000000000000000000000000000000000000000000000000000000"
        },
        {
          "__typename": "ChangeOutput",
          "to": "0xdd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a",
          "amount": "6089511094",
          "assetId": "0x0000000000000000000000000000000000000000000000000000000000000000"
        }
      ],
      "maturity": "0",
      "receiptsRoot": "0xb4e171919e885edbf5be1ed0b2c544148319c4bc2b5adad0cd8c220256185880",
      "status": {
        "__typename": "SuccessStatus",
        "block": {
          "id": "0xadd8e5cab0cecb3c260cb971dabcba46c277bb80c6af76addc4b9dba13e558e8"
        },
        "time": "4611686020129743884",
        "programState": {
          "returnType": "RETURN",
          "data": "0x0000000000000001"
        }
      },
      "witnesses": [],
      "receipts": [
        {
          "param1": null,
          "param2": null,
          "amount": null,
          "assetId": null,
          "gas": null,
          "digest": null,
          "contract": null,
          "is": "10344",
          "pc": "10344",
          "ptr": null,
          "ra": null,
          "rb": null,
          "rc": null,
          "rd": null,
          "reason": null,
          "receiptType": "RETURN",
          "to": null,
          "toAddress": null,
          "val": "1",
          "len": null,
          "result": null,
          "gasUsed": null,
          "data": null,
          "sender": null,
          "recipient": null,
          "nonce": null,
          "contractId": null,
          "subId": null
        },
        {
          "param1": null,
          "param2": null,
          "amount": null,
          "assetId": null,
          "gas": null,
          "digest": null,
          "contract": null,
          "is": null,
          "pc": null,
          "ptr": null,
          "ra": null,
          "rb": null,
          "rc": null,
          "rd": null,
          "reason": null,
          "receiptType": "SCRIPT_RESULT",
          "to": null,
          "toAddress": null,
          "val": null,
          "len": null,
          "result": "0",
          "gasUsed": "8872",
          "data": null,
          "sender": null,
          "recipient": null,
          "nonce": null,
          "contractId": null,
          "subId": null
        }
      ],
      "script": "0x",
      "scriptData": "0x",
      "salt": null,
      "storageSlots": null,
      "bytecodeWitnessIndex": null,
      "bytecodeLength": null
    }
  }
}

so basically take:

from:

"inputs": [
        {
          "__typename": "InputCoin",
          "utxoId": "0xe5a18811e6f6949ef0382c802c062626009ebdf22b0529d912f90910ee833bd900",
          "owner": "0xdd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a",
          "amount": "17100000000",
          "assetId": "0x0000000000000000000000000000000000000000000000000000000000000000",
          "txPointer": "000000000000",
          "witnessIndex": 0,
          "maturity": "0",
          "predicateGasUsed": "4436",
          "predicateData": 
...

to:

      "outputs": [
        {
          "__typename": "CoinOutput",
          "to": "0xf0f5ddf97f6b5a74efa7877f37f092b38f6ba492abf76f1556941adc40b30e4a",
          "amount": "11200000000",
          "assetId": "0x0000000000000000000000000000000000000000000000000000000000000000"
        },

thanks!

@Voxelot yours produces a more succinct output (same txid):

{
  "data": {
    "transaction": {
      "inputs": [
        {
          "owner": "0xdd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a",
          "__typename": "InputCoin"
        },
        {
          "owner": "0xdd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a",
          "__typename": "InputCoin"
        }
      ],
      "outputs": [
        {
          "__typename": "CoinOutput",
          "to": "0xf0f5ddf97f6b5a74efa7877f37f092b38f6ba492abf76f1556941adc40b30e4a"
        },
        {
          "__typename": "ChangeOutput",
          "to": "0xdd75c3ab12375b6baff69c18c11ce8d3b501cbce24ded405d087400c78a4004a"
        }
      ]
    }
  }
}

It may be considered somewhat cumbersome having multiple payers and receivers on a single transaction. However, this also unlocks many efficiencies and new functional capabilities such as parallel execution, account abstraction, and native meta-transactions (i.e. pay gas in alt-tokens or paymasters etc)

absolutely! this is what we are working towards :slight_smile: