-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5dc75d5
Showing
191 changed files
with
47,663 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<img src="/logo.png" width="25%" /> | ||
|
||
# Godot Web3 Plugin | ||
|
||
Godot plugin for building web3 games. | ||
|
||
## Building | ||
|
||
Clone `godot` and copy sources to `modules/web3`. | ||
|
||
``` | ||
|-- godot | ||
|-- modules | ||
| |-- web3 | ||
``` | ||
|
||
Build from `godot` root. | ||
|
||
```bash | ||
scons custom_modules=../modules platform=osx arch=arm64 --jobs=$(sysctl -n hw.logicalcpu) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/usr/bin/env python | ||
|
||
Import('env') | ||
|
||
env_module = env.Clone() | ||
env_module.Prepend(CPPPATH=["thirdparty/trezor-crypto"]) | ||
env_module.Append(CDEFINES=["USE_KECCAK", "USE_ETHEREUM"]) | ||
|
||
env_trezor_crypto = env_module.Clone() | ||
env_trezor_crypto.disable_warnings() | ||
env_trezor_crypto.add_source_files(env.modules_sources, "thirdparty/trezor-crypto/*.c") | ||
|
||
env_module.add_source_files(env.modules_sources, "*.cpp") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
#include "abi.h" | ||
|
||
#include "keccak.h" | ||
|
||
#include "core/io/json.h" | ||
#include "core/os/file_access.h" | ||
|
||
String ABI::encode_uint256(const int p_value) { | ||
return String::num_int64(p_value, 16).lpad(64, "0"); | ||
} | ||
|
||
int ABI::decode_uint256(const String &p_value) { | ||
return p_value.hex_to_int(false); | ||
} | ||
|
||
String ABI::encode_address(const String &p_address) { | ||
return p_address.trim_prefix("0x").lpad(64, "0"); | ||
} | ||
|
||
String ABI::decode_address(const String &p_value) { | ||
return p_value.substr(44); | ||
} | ||
|
||
String ABI::encode_array(const Array &p_array) { | ||
String encoded; | ||
for (int i = 0; i < p_array.size(); i++) { | ||
encoded += encode_address(p_array[i]); | ||
} | ||
return encoded; | ||
} | ||
|
||
Array ABI::decode_array(const String &p_value, const int p_length, const String &p_type) { | ||
Array array; | ||
for (int i = 0; i < p_length; i++) { | ||
String entry = p_value.substr(i * 64, 64); | ||
if (p_type == "address") { | ||
array.push_back(decode_address(entry)); | ||
} else if (p_type == "uint256") { | ||
array.push_back(decode_uint256(entry)); | ||
} | ||
} | ||
return array; | ||
} | ||
|
||
String ABI::encode_function(const String &p_name, const Array &p_inputs) { | ||
ERR_FAIL_COND_V_MSG(!functions.has(p_name), String(), "Method doesn't exist"); | ||
|
||
Function function = functions[p_name]; | ||
Vector<Parameter> inputs = function.inputs; | ||
|
||
// ERR_FAIL_COND_V_MSG(inputs.size() != p_inputs.size(), String(), "Method inputs don't match"); | ||
|
||
String head; | ||
String body; | ||
|
||
int offset = p_inputs.size(); | ||
for (int i = 0; i < inputs.size(); i++) { | ||
Parameter input = inputs[i]; | ||
if (input.type == "address" || input.type == "uint256") { | ||
String value = p_inputs[i]; | ||
head += encode_address(value); | ||
} else if (input.type == "address[]" || input.type == "uint256[]") { | ||
Array value = p_inputs[i]; | ||
head += encode_uint256(offset * 32); | ||
body += encode_uint256(value.size()); | ||
body += encode_array(value); | ||
offset += value.size() + 1; | ||
} else { | ||
ERR_FAIL_COND_V_MSG(true, String(), "Unsupported input type"); | ||
} | ||
} | ||
|
||
return "0x" + function.signature + head + body; | ||
} | ||
|
||
Array ABI::decode_function(const String &p_name, const String &p_value) { | ||
ERR_FAIL_COND_V_MSG(!functions.has(p_name), Array(), "Method doesn't exist"); | ||
|
||
Function function = functions[p_name]; | ||
Vector<Parameter> outputs = function.outputs; | ||
|
||
Array out; | ||
String enc = p_value.trim_prefix("0x"); | ||
|
||
for (int i = 0; i < outputs.size(); i++) { | ||
Parameter output = outputs[i]; | ||
if (output.type == "address") { | ||
String data = enc.substr(i * 64, 64); | ||
String value = decode_address(data); | ||
out.push_back(value); | ||
} else if (output.type == "uint256") { | ||
String data = enc.substr(i * 64, 64); | ||
int value = decode_uint256(data); | ||
out.push_back(value); | ||
} else if (output.type == "address[]") { | ||
int offset = enc.substr(i * 64, 64).hex_to_int(false); | ||
int length = enc.substr(offset * 2, 64).hex_to_int(false); | ||
String data = enc.substr(offset * 2 + 64, length * 64); | ||
Array value = decode_array(data, length, "address"); | ||
out.push_back(value); | ||
} else if (output.type == "uint256[]") { | ||
int offset = enc.substr(i * 64, 64).hex_to_int(false); | ||
int length = enc.substr(offset * 2, 64).hex_to_int(false); | ||
String data = enc.substr(offset * 2 + 64, length * 64); | ||
Array value = decode_array(data, length, "uint256"); | ||
out.push_back(value); | ||
} | ||
} | ||
|
||
return out; | ||
} | ||
|
||
Error ABI::parse(const String &p_json) { | ||
String error_string; | ||
int error_line; | ||
Variant json; | ||
|
||
Error error = JSON::parse(p_json, json, error_string, error_line); | ||
ERR_FAIL_COND_V(error, error); | ||
|
||
Array entries = json; | ||
for (int i = 0; i < entries.size(); i++) { | ||
Dictionary entry = entries[i]; | ||
String type = entry["type"]; | ||
|
||
if (type == "function" || type == "receive" || type == "fallback") { | ||
parse_function(entry); | ||
} | ||
} | ||
|
||
return OK; | ||
} | ||
|
||
void ABI::parse_function(const Dictionary &p_function) { | ||
Function function; | ||
function.name = p_function["name"]; | ||
function.type = p_function["type"]; | ||
|
||
Array input_params = p_function["inputs"]; | ||
for (int i = 0; i < input_params.size(); i++) { | ||
Dictionary param = input_params[i]; | ||
|
||
Parameter input; | ||
input.name = param["name"]; | ||
input.type = param["type"]; | ||
|
||
function.inputs.push_back(input); | ||
} | ||
|
||
Array output_params = p_function["outputs"]; | ||
for (int i = 0; i < output_params.size(); i++) { | ||
Dictionary param = output_params[i]; | ||
|
||
Parameter output; | ||
output.name = param["name"]; | ||
output.type = param["type"]; | ||
|
||
function.outputs.push_back(output); | ||
} | ||
|
||
Vector<String> inputs; | ||
for (int i = 0; i < function.inputs.size(); i++) { | ||
inputs.push_back(function.inputs[i].type); | ||
} | ||
|
||
String signature; | ||
signature += function.name; | ||
signature += "("; | ||
signature += String(",").join(inputs); | ||
signature += ")"; | ||
|
||
CharString cs = signature.utf8(); | ||
uint8_t hash[32]; | ||
|
||
Keccak::hash((unsigned char *)cs.ptr(), cs.length(), hash); | ||
function.signature = String::hex_encode_buffer(hash, 4); | ||
|
||
functions[function.name] = function; | ||
} | ||
|
||
void ABI::_bind_methods() { | ||
ClassDB::bind_method(D_METHOD("parse", "json"), &ABI::parse); | ||
} | ||
|
||
// ResourceFormatLoader | ||
|
||
RES ResourceFormatLoaderABI::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_no_subresource_cache) { | ||
Vector<uint8_t> buffer = FileAccess::get_file_as_array(p_path); | ||
|
||
String str; | ||
str.parse_utf8((const char *)buffer.ptr(), buffer.size()); | ||
|
||
Ref<ABI> abi = memnew(ABI); | ||
Error error = abi->parse(str); | ||
|
||
if (r_error) { | ||
*r_error = error; | ||
} | ||
|
||
return abi; | ||
} | ||
|
||
void ResourceFormatLoaderABI::get_recognized_extensions(List<String> *r_extensions) const { | ||
r_extensions->push_back("json"); | ||
} | ||
|
||
String ResourceFormatLoaderABI::get_resource_type(const String &p_path) const { | ||
String el = p_path.get_extension().to_lower(); | ||
if (el == "json") { | ||
return "ABI"; | ||
} | ||
return ""; | ||
} | ||
|
||
bool ResourceFormatLoaderABI::handles_type(const String &p_type) const { | ||
return (p_type == "ABI"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#ifndef ABI_H | ||
#define ABI_H | ||
|
||
#include "core/io/resource_loader.h" | ||
#include "core/resource.h" | ||
|
||
class ABI : public Resource { | ||
GDCLASS(ABI, Resource); | ||
|
||
struct Parameter { | ||
String type; | ||
String name; | ||
Vector<Parameter> components; | ||
}; | ||
|
||
struct Function { | ||
String type; | ||
String name; | ||
String signature; | ||
Vector<Parameter> inputs; | ||
Vector<Parameter> outputs; | ||
}; | ||
|
||
HashMap<String, Function> functions; | ||
void parse_function(const Dictionary &p_function); | ||
|
||
protected: | ||
static void _bind_methods(); | ||
|
||
public: | ||
Error parse(const String &p_json); | ||
|
||
Array decode_array(const String &p_value, const int p_length, const String &p_type); | ||
String encode_array(const Array &p_array); | ||
|
||
String encode_uint256(const int p_value); | ||
int decode_uint256(const String &p_value); | ||
|
||
String encode_address(const String &p_value); | ||
String decode_address(const String &p_value); | ||
|
||
String encode_function(const String &p_name, const Array &p_inputs); | ||
Array decode_function(const String &p_name, const String &p_value); | ||
}; | ||
|
||
class ResourceFormatLoaderABI : public ResourceFormatLoader { | ||
GDCLASS(ResourceFormatLoaderABI, ResourceFormatLoader); | ||
public: | ||
virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_no_subresource_cache = false); | ||
virtual void get_recognized_extensions(List<String> *r_extensions) const; | ||
virtual bool handles_type(const String &p_type) const; | ||
virtual String get_resource_type(const String &p_path) const; | ||
}; | ||
|
||
#endif // ABI_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
def can_build(env, platform): | ||
return True | ||
|
||
def configure(env): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#include "eth_balance.h" | ||
|
||
Error EthBalance::request(const String &p_address) { | ||
Array params; | ||
params.push_back(p_address); | ||
params.push_back("latest"); | ||
|
||
return rpc_request->request("eth_getBalance", params); | ||
} | ||
|
||
void EthBalance::_request_completed(int p_status, const Dictionary &p_result) { | ||
emit_signal("request_completed", p_status, p_result["result"]); | ||
} | ||
|
||
void EthBalance::_bind_methods() { | ||
ClassDB::bind_method(D_METHOD("request", "address"), &EthBalance::request); | ||
ClassDB::bind_method("_request_completed", &EthBalance::_request_completed); | ||
|
||
ADD_SIGNAL(MethodInfo("request_completed", PropertyInfo(Variant::INT, "status"), PropertyInfo(Variant::STRING, "result"))); | ||
} | ||
|
||
EthBalance::EthBalance() { | ||
rpc_request = memnew(RPCRequest); | ||
add_child(rpc_request); | ||
rpc_request->connect("request_completed", this, "_request_completed"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#ifndef ETH_BALANCE_H | ||
#define ETH_BALANCE_H | ||
|
||
#include "scene/main/node.h" | ||
|
||
#include "rpc_request.h" | ||
|
||
class EthBalance : public Node { | ||
GDCLASS(EthBalance, Node); | ||
|
||
RPCRequest *rpc_request = nullptr; | ||
void _request_completed(int p_status, const Dictionary &p_result); | ||
|
||
protected: | ||
static void _bind_methods(); | ||
|
||
public: | ||
Error request(const String &p_address); | ||
|
||
EthBalance(); | ||
}; | ||
|
||
#endif // ETH_BALANCE_H |
Oops, something went wrong.