web3p / web3.php

A php interface for interacting with the Ethereum blockchain and ecosystem. Native ABI parsing and smart contract interactions.
MIT License
1.17k stars 555 forks source link

Error "Undefined array key "coders"" #346

Open bjutkoski opened 9 months ago

bjutkoski commented 9 months ago

I'm having this error Undefined array key "coders" when methods has tuple[] or tuple as input/output

/web3p/web3.php/src/Contracts/Types/Tuple.php:116

input as tuple[]

{ "inputs": [ { "internalType": "string", "name": "documentId", "type": "string" }, { "components": [ { "internalType": "string", "name": "documentItemId", "type": "string" }, { "internalType": "string", "name": "id", "type": "string" }, { "internalType": "string", "name": "locationId", "type": "string" }, { "internalType": "string", "name": "wasteId", "type": "string" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "internalType": "struct WasteTraceability.CollectionRequestItem[]", "name": "collectionRequestItems", "type": "tuple[]" } ], "name": "createCollectionRequest", "outputs": [], "stateMutability": "nonpayable", "type": "function" }

tuple as output

{ "inputs": [ { "internalType": "string", "name": "wasteId", "type": "string" } ], "name": "getWaste", "outputs": [ { "components": [ { "internalType": "string", "name": "name", "type": "string" }, { "internalType": "uint256", "name": "decimals", "type": "uint256" } ], "internalType": "struct WasteTraceability.Waste", "name": "", "type": "tuple" } ], "stateMutability": "view", "type": "function" }

Ow3nTan commented 7 months ago

i am encountering the same issue now

ShravanVerma commented 4 months ago

I have same issue while reading tuple data output

I have modified Ethabi class decodeParameters function as given below and its working fine:

public function decodeParameters($types, $param) { if (!is_string($param)) { throw new InvalidArgumentException('The param must be string.'); }

    // change json to array
    $outputTypes = [];
    if ($types instanceof stdClass && isset($types->outputs)) {
        $types = Utils::jsonToArray($types, 2);
    }
    if (is_array($types) && isset($types['outputs'])) {
        $outputTypes = $types;
        $types = [];
        if(!empty($outputTypes['outputs'][0]['components']))
        {
            foreach ($outputTypes['outputs'][0]['components'] as $component) {
                $types[] = $component['type'];
            }
        }
        else{
            foreach ($outputTypes['outputs'] as $output) {
                if (isset($output['type'])) {
                    $types[] = $output['type'];
                }
            }
        }
    }
    $typesLength = count($types);
    $abiTypes = $this->parseAbiTypes($types);

    // decode with tuple type
    $results = [];
    $decodeResults = $this->types['tuple']->decode(Utils::stripZero($param), 0, [ 'coders' => $abiTypes ]);
    for ($i = 0; $i < $typesLength; $i++) {

        if(!empty($outputTypes['outputs'][0]['components']))
        {
            if (isset($outputTypes['outputs'][0]['components'][$i]['name']) && empty($outputTypes['outputs'][0]['components'][$i]['name']) === false) {
                $results[$outputTypes['outputs'][0]['components'][$i]['name']] = $decodeResults[$i];
            } else {
                $results[$i] = $decodeResults[$i];
            }
        }
        else{
            if (isset($outputTypes['outputs'][$i]['name']) && empty($outputTypes['outputs'][$i]['name']) === false) {
                $results[$outputTypes['outputs'][$i]['name']] = $decodeResults[$i];
            } else {
                $results[$i] = $decodeResults[$i];
            }
        }

    }
    return $results;
}
ShravanVerma commented 4 months ago

I have same issue while reading tuple data output

I have modified Ethabi class decodeParameters function as given below and its working fine:

public function decodeParameters($types, $param) { if (!is_string($param)) { throw new InvalidArgumentException('The param must be string.'); }

// change json to array
$outputTypes = [];
if ($types instanceof stdClass && isset($types->outputs)) {
    $types = Utils::jsonToArray($types, 2);
}
if (is_array($types) && isset($types['outputs'])) {
    $outputTypes = $types;
    $types = [];
    if(!empty($outputTypes['outputs'][0]['components']))
    {
        foreach ($outputTypes['outputs'][0]['components'] as $component) {
            $types[] = $component['type'];
        }
    }
    else{
        foreach ($outputTypes['outputs'] as $output) {
            if (isset($output['type'])) {
                $types[] = $output['type'];
            }
        }
    }
}
$typesLength = count($types);
$abiTypes = $this->parseAbiTypes($types);

// decode with tuple type
$results = [];
$decodeResults = $this->types['tuple']->decode(Utils::stripZero($param), 0, [ 'coders' => $abiTypes ]);
for ($i = 0; $i < $typesLength; $i++) {

    if(!empty($outputTypes['outputs'][0]['components']))
    {
        if (isset($outputTypes['outputs'][0]['components'][$i]['name']) && empty($outputTypes['outputs'][0]['components'][$i]['name']) === false) {
            $results[$outputTypes['outputs'][0]['components'][$i]['name']] = $decodeResults[$i];
        } else {
            $results[$i] = $decodeResults[$i];
        }
    }
    else{
        if (isset($outputTypes['outputs'][$i]['name']) && empty($outputTypes['outputs'][$i]['name']) === false) {
            $results[$outputTypes['outputs'][$i]['name']] = $decodeResults[$i];
        } else {
            $results[$i] = $decodeResults[$i];
        }
    }

}
return $results;

}

fengxin2017 commented 4 months ago

I have same issue while reading tuple data output

I have modified Ethabi class decodeParameters function as given below and its working fine:

public function decodeParameters($types, $param) { if (!is_string($param)) { throw new InvalidArgumentException('The param must be string.'); }

    // change json to array
    $outputTypes = [];
    if ($types instanceof stdClass && isset($types->outputs)) {
        $types = Utils::jsonToArray($types, 2);
    }
    if (is_array($types) && isset($types['outputs'])) {
        $outputTypes = $types;
        $types = [];
        if(!empty($outputTypes['outputs'][0]['components']))
        {
            foreach ($outputTypes['outputs'][0]['components'] as $component) {
                $types[] = $component['type'];
            }
        }
        else{
            foreach ($outputTypes['outputs'] as $output) {
                if (isset($output['type'])) {
                    $types[] = $output['type'];
                }
            }
        }
    }
    $typesLength = count($types);
    $abiTypes = $this->parseAbiTypes($types);

    // decode with tuple type
    $results = [];
    $decodeResults = $this->types['tuple']->decode(Utils::stripZero($param), 0, [ 'coders' => $abiTypes ]);
    for ($i = 0; $i < $typesLength; $i++) {

        if(!empty($outputTypes['outputs'][0]['components']))
        {
            if (isset($outputTypes['outputs'][0]['components'][$i]['name']) && empty($outputTypes['outputs'][0]['components'][$i]['name']) === false) {
                $results[$outputTypes['outputs'][0]['components'][$i]['name']] = $decodeResults[$i];
            } else {
                $results[$i] = $decodeResults[$i];
            }
        }
        else{
            if (isset($outputTypes['outputs'][$i]['name']) && empty($outputTypes['outputs'][$i]['name']) === false) {
                $results[$outputTypes['outputs'][$i]['name']] = $decodeResults[$i];
            } else {
                $results[$i] = $decodeResults[$i];
            }
        }

    }
    return $results;
}

nice