smartcontractkit / chainlink

node of the decentralized oracle network, bridging on and off-chain computation
https://chain.link
Other
7.02k stars 1.71k forks source link

[NODE] Return bytes32 from TOML job. v1.2.1 #6499

Closed aelmanaa closed 2 years ago

aelmanaa commented 2 years ago

Description Hello,

tried to create the following job specs which fetch data from an API, parse the response, and returns the result as bytes32. Not 100% sure but I think this was possible with the ethbytes32 legacy adapter The job fails while encoding the data ( the response that I got after parsing is "Kraken" which indeed is of length 6)

ETHABIEncode: while converting argument 'value' from <nil> to bytes32: incorrect length: expected 32, got 6: bad input for task: bad input for task

abi: (bytes32 value)

data: { "value": $(parse) }

Steps to Reproduce

type = "directrequest"
schemaVersion = 1
name = "Get > Bytes32 - (TOML)"
maxTaskDuration = "0s"
contractAddress = "YOUR_CONTRACT_ADDRESS"
minIncomingConfirmations = 0
observationSource = """
    decode_log   [type="ethabidecodelog"
                  abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)"
                  data="$(jobRun.logData)"
                  topics="$(jobRun.logTopics)"]

    decode_cbor  [type="cborparse" data="$(decode_log.data)"]
    fetch        [type="http" method=GET url="$(decode_cbor.get)"]
    parse        [type="jsonparse" path="$(decode_cbor.path)" data="$(fetch)"]
    encode_data  [type="ethabiencode" abi="(bytes32 value)" data="{ \\"value\\": $(parse) }"]
    encode_tx    [type="ethabiencode"
                  abi="fulfillOracleRequest(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes32 data)"
                  data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\":   $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}"
                  ]
    submit_tx    [type="ethtx" to="YOUR_CONTRACT_ADDRESS" data="$(encode_tx)"]

    decode_log -> decode_cbor -> fetch -> parse -> encode_data -> encode_tx -> submit_tx
"""
Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
        req.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");
        string[] memory path = new string[](4);
        path[0] = "RAW";
        path[1] = "ETH";
        path[2] = "USD";
        path[3] = "LASTMARKET";
        req.addStringArray("path", path);
        return sendChainlinkRequest(req, fee);

Additional Information How to configure the ethabiencode task to get bytes32 like it was done for the ethbytes32 legacy adapter

PatrickAlphaC commented 2 years ago

Thank you! Will investigate.

aelmanaa commented 2 years ago

I had a discussion with @pinebit: the legacy ethbytes32 converted the input to string before encoding it to bytes32. Here, I was trying to directly encode to bytes32 and that s why I had an issue.

The best is to work with generic jobs that provide specific data types like it is done here:

Hence, this Example should be updated to use a "Get > string" job