Skip to content

Commit

Permalink
Add JsonRPC protocol contract (#43)
Browse files Browse the repository at this point in the history
* Add JsonRPC protocol contract

* Rename JsonRPC to EthJsonRPC

* Update forge

* Fix README

* Update README

* Update README
  • Loading branch information
ferranbt authored Feb 19, 2024
1 parent e1b6b85 commit 864656e
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 3 deletions.
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,27 @@ contract Example {
}
```

### protocols/ChatGPT.sol
### protocols/EthJsonRPC.sol

Helper library to send completion requests to ChatGPT.
Helper library to interact with the Ethereum JsonRPC protocol.

#### Example usage

```solidity
import "suave-std/protocols/EthJsonRPC.sol";
contract Example {
function example() {
EthJsonRPC jsonrpc = new EthJsonRPC("http://...");
jsonrpc.nonce(address(this));
}
}
```

### protocols/ChatGPT.sol

Helper library to send completion requests to ChatGPT.

```solidity
import "suave-std/protocols/ChatGPT.sol";
Expand Down
2 changes: 1 addition & 1 deletion lib/forge-std
57 changes: 57 additions & 0 deletions src/protocols/EthJsonRPC.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;

import "src/suavelib/Suave.sol";
import "solady/src/utils/JSONParserLib.sol";
import "solady/src/utils/LibString.sol";

contract EthJsonRPC {
using JSONParserLib for *;

string endpoint;

constructor(string memory _endpoint) {
endpoint = _endpoint;
}

function nonce(address addr) public returns (uint256) {
bytes memory body = abi.encodePacked(
'{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["',
LibString.toHexStringChecksummed(addr),
'","latest"],"id":1}'
);

JSONParserLib.Item memory item = doRequest(string(body));
uint256 val = JSONParserLib.parseUintFromHex(trimQuotes(item.value()));
return val;
}

function doRequest(string memory body) public returns (JSONParserLib.Item memory) {
Suave.HttpRequest memory request;
request.method = "POST";
request.url = endpoint;
request.headers = new string[](1);
request.headers[0] = "Content-Type: application/json";
request.body = bytes(body);

bytes memory output = Suave.doHTTPRequest(request);

JSONParserLib.Item memory item = string(output).parse();
return item.at('"result"');
}

function trimQuotes(string memory input) private pure returns (string memory) {
bytes memory inputBytes = bytes(input);
require(
inputBytes.length >= 2 && inputBytes[0] == '"' && inputBytes[inputBytes.length - 1] == '"', "Invalid input"
);

bytes memory result = new bytes(inputBytes.length - 2);

for (uint256 i = 1; i < inputBytes.length - 1; i++) {
result[i - 1] = inputBytes[i];
}

return string(result);
}
}
24 changes: 24 additions & 0 deletions test/protocols/EthJsonRPC.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "forge-std/Test.sol";
import "src/Test.sol";
import "solady/src/utils/LibString.sol";
import "src/protocols/EthJsonRPC.sol";

contract EthJsonRPCTest is Test, SuaveEnabled {
function testEthJsonRPCGetNonce() public {
EthJsonRPC ethjsonrpc = getEthJsonRPC();

uint256 nonce = ethjsonrpc.nonce(address(this));
assertEq(nonce, 0);
}

function getEthJsonRPC() public returns (EthJsonRPC ethjsonrpc) {
try vm.envString("JSONRPC_ENDPOINT") returns (string memory endpoint) {
ethjsonrpc = new EthJsonRPC(endpoint);
} catch {
vm.skip(true);
}
}
}

0 comments on commit 864656e

Please sign in to comment.