From c7acd04dc9dfb75aefa9db2e63b9ddbccde43759 Mon Sep 17 00:00:00 2001 From: Ryan Leckey Date: Wed, 15 Jun 2022 10:05:41 -0700 Subject: [PATCH] feat(go): setup some initial bindings for the v3 Go SDK --- .gitignore | 1 + sdk/go/account_address.go | 10 ++ sdk/go/account_alias.go | 13 ++ sdk/go/account_id.go | 23 +-- sdk/go/client.go | 29 ++++ sdk/go/key.go | 6 + sdk/go/native.go | 9 ++ sdk/go/native/hedera.h | 214 +++++++++++++++++++++++++ sdk/go/native/linux/amd64/package.go | 1 + sdk/go/native/linux/package.go | 3 + sdk/go/native/macos/amd64/package.go | 1 + sdk/go/native/macos/arm64/package.go | 1 + sdk/go/native/macos/package.go | 6 + sdk/go/native/package.go | 7 + sdk/go/native/windows/amd64/package.go | 1 + sdk/go/native/windows/package.go | 3 + sdk/go/public_key.go | 8 + sdk/rust/Taskfile.yml | 19 ++- sdk/rust/src/key/key.rs | 1 + 19 files changed, 329 insertions(+), 27 deletions(-) create mode 100644 sdk/go/account_address.go create mode 100644 sdk/go/account_alias.go create mode 100644 sdk/go/client.go create mode 100644 sdk/go/key.go create mode 100644 sdk/go/native.go create mode 100644 sdk/go/native/hedera.h create mode 100644 sdk/go/native/linux/amd64/package.go create mode 100644 sdk/go/native/linux/package.go create mode 100644 sdk/go/native/macos/amd64/package.go create mode 100644 sdk/go/native/macos/arm64/package.go create mode 100644 sdk/go/native/macos/package.go create mode 100644 sdk/go/native/package.go create mode 100644 sdk/go/native/windows/amd64/package.go create mode 100644 sdk/go/native/windows/package.go create mode 100644 sdk/go/public_key.go diff --git a/.gitignore b/.gitignore index 1f8aba86..1e4e8386 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .task/ sdk/c/lib/*/ sdk/swift/CHedera.xcframework/*/ +sdk/go/native/**/*.a diff --git a/sdk/go/account_address.go b/sdk/go/account_address.go new file mode 100644 index 00000000..6ab722fc --- /dev/null +++ b/sdk/go/account_address.go @@ -0,0 +1,10 @@ +package hedera + +/// AccountAddress is either `AccountId` or `AccountAlias`. +/// +/// Some transactions and queries accept `AccountAddress` as an input. +/// All transactions and queries return only `AccountId` as an output however. +/// +type AccountAddress interface { + _isAccountAlias() bool +} diff --git a/sdk/go/account_alias.go b/sdk/go/account_alias.go new file mode 100644 index 00000000..fe48aa59 --- /dev/null +++ b/sdk/go/account_alias.go @@ -0,0 +1,13 @@ +package hedera + +/// AccountAlias is the unique identifier for a cryptocurrency account on Hedera, +/// represented with an alias instead of an account number. +type AccountAlias struct { + Shard uint64 + Realm uint64 + Alias PublicKey +} + +func (accountAlias AccountAlias) _isAccountAlias() bool { + return true +} diff --git a/sdk/go/account_id.go b/sdk/go/account_id.go index b9bdd3f0..2c9abcb7 100644 --- a/sdk/go/account_id.go +++ b/sdk/go/account_id.go @@ -7,27 +7,6 @@ type AccountID struct { Num uint64 } -func (alias AccountID) _isAccountAlias() bool { +func (accountID AccountID) _isAccountAlias() bool { return false } - -/// AccountAlias is the unique identifier for a cryptocurrency account on Hedera, -/// represented with an alias instead of an account number. -type AccountAlias struct { - Shard uint64 - Realm uint64 - Alias PublicKey -} - -func (alias AccountAlias) _isAccountAlias() bool { - return true -} - -/// AccountIDOrAlias is either `AccountId` or `AccountAlias`. -/// -/// Some transactions and queries accept `AccountIdOrAlias` as an input. -/// All transactions and queries return only `AccountId` as an output however. -/// -type AccountIDOrAlias interface { - _isAccountAlias() bool -} diff --git a/sdk/go/client.go b/sdk/go/client.go new file mode 100644 index 00000000..85fe1328 --- /dev/null +++ b/sdk/go/client.go @@ -0,0 +1,29 @@ +package hedera + +// #include "native/hedera.h" +import "C" + +import "runtime" + +// Client provides a connection to the Hedera network. +type Client struct { + ptr *C.HederaClient +} + +// ClientForTestnet constructs a Hedera client pre-configured for testnet access. +func ClientForTestnet() *Client { + return _makeClient(C.hedera_client_for_testnet()) +} + +func _makeClient(ptr *C.HederaClient) *Client { + client := new(Client) + client.ptr = ptr + + runtime.SetFinalizer(client, _clientFinalizer) + + return client +} + +func _clientFinalizer(client *Client) { + C.hedera_client_free(client.ptr) +} diff --git a/sdk/go/key.go b/sdk/go/key.go new file mode 100644 index 00000000..e37337dd --- /dev/null +++ b/sdk/go/key.go @@ -0,0 +1,6 @@ +package hedera + +// Key describes a method that can be used to authorize an operation on Hedera. +type Key interface { + _isKey() bool +} diff --git a/sdk/go/native.go b/sdk/go/native.go new file mode 100644 index 00000000..8747721c --- /dev/null +++ b/sdk/go/native.go @@ -0,0 +1,9 @@ +package hedera + +// #cgo CFLAGS: -g -Wall +// #include "native/hedera.h" +// #cgo linux,amd64 LDFLAGS: ${SRCDIR}/native/linux/libhedera.a -ldl -lm +// #cgo darwin,amd64 LDFLAGS: ${SRCDIR}/native/macos/amd64/libhedera.a -ldl -lm +// #cgo darwin,arm64 LDFLAGS: ${SRCDIR}/native/macos/arm64/libhedera.a -ldl -lm +// #cgo windows,amd64 LDFLAGS: ${SRCDIR}/native/windows/libhedera.a -lm +import "C" diff --git a/sdk/go/native/hedera.h b/sdk/go/native/hedera.h new file mode 100644 index 00000000..40dd445a --- /dev/null +++ b/sdk/go/native/hedera.h @@ -0,0 +1,214 @@ +#ifndef _HEDERA_H +#define _HEDERA_H + +/* Generated with cbindgen:0.23.0 */ + +#include +#include +#include +#include + +/** + * Represents any possible result from a fallible function in the Hedera SDK. + */ +typedef enum HederaError { + HEDERA_ERROR_OK, + HEDERA_ERROR_TIMED_OUT, + HEDERA_ERROR_GRPC_STATUS, + HEDERA_ERROR_FROM_PROTOBUF, + HEDERA_ERROR_TRANSACTION_PRE_CHECK_STATUS, + HEDERA_ERROR_TRANSACTION_NO_ID_PRE_CHECK_STATUS, + HEDERA_ERROR_QUERY_PRE_CHECK_STATUS, + HEDERA_ERROR_QUERY_PAYMENT_PRE_CHECK_STATUS, + HEDERA_ERROR_QUERY_NO_PAYMENT_PRE_CHECK_STATUS, + HEDERA_ERROR_BASIC_PARSE, + HEDERA_ERROR_KEY_PARSE, + HEDERA_ERROR_NO_PAYER_ACCOUNT_OR_TRANSACTION_ID, + HEDERA_ERROR_MAX_QUERY_PAYMENT_EXCEEDED, + HEDERA_ERROR_NODE_ACCOUNT_UNKNOWN, + HEDERA_ERROR_RESPONSE_STATUS_UNRECOGNIZED, + HEDERA_ERROR_RECEIPT_STATUS, + HEDERA_ERROR_SIGNATURE, + HEDERA_ERROR_REQUEST_PARSE, +} HederaError; + +/** + * Managed client for use on the Hedera network. + */ +typedef struct HederaClient HederaClient; + +/** + * A private key on the Hedera network. + */ +typedef struct HederaPrivateKey HederaPrivateKey; + +/** + * A public key on the Hedera network. + */ +typedef struct HederaPublicKey HederaPublicKey; + +/** + * An opaque signer that can sign Hedera transactions. + * + * Intended to be a temporary object that is generalized and passed into + * a function accepting a `HederaSigner*`. Failure to do so will result in + * a memory of leak. + */ +typedef struct HederaSigner HederaSigner; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Returns English-language text that describes the last error. Undefined if there has been + * no last error. + */ +const char *hedera_error_message(void); + +/** + * Returns the GRPC status code for the last error. Undefined if the last error was not + * `HEDERA_ERROR_GRPC_STATUS`. + */ +int32_t hedera_error_grpc_status(void); + +/** + * Returns the hedera services response code for the last error. Undefined if the last error + * was not `HEDERA_ERROR_PRE_CHECK_STATUS`. + */ +int32_t hedera_error_pre_check_status(void); + +/** + * Parse a Hedera `AccountAddress` from the passed string. + */ +enum HederaError hedera_account_address_from_string(const char *s, + uint64_t *id_shard, + uint64_t *id_realm, + uint64_t *id_num, + struct HederaPublicKey **id_alias); + +/** + * Parse a Hedera `AccountAlias` from the passed string. + */ +enum HederaError hedera_account_alias_from_string(const char *s, + uint64_t *id_shard, + uint64_t *id_realm, + struct HederaPublicKey **id_alias); + +/** + * Construct a Hedera client pre-configured for testnet access. + */ +struct HederaClient *hedera_client_for_testnet(void); + +/** + * Release memory associated with the previously-opened Hedera client. + */ +void hedera_client_free(struct HederaClient *client); + +/** + * Sets the account that will, by default, be paying for transactions and queries built with + * this client. + */ +void hedera_client_set_payer_account_id(struct HederaClient *client, + uint64_t id_shard, + uint64_t id_realm, + uint64_t id_num); + +/** + * Gets the account that is, by default, paying for transactions and queries built with + * this client. + */ +void hedera_client_get_payer_account_id(struct HederaClient *client, + uint64_t *id_shard, + uint64_t *id_realm, + uint64_t *id_num); + +/** + * Adds a signer that will, by default, sign for all transactions and queries built + * with this client. + * + * Takes ownership of the passed signer. + * + */ +void hedera_client_add_default_signer(struct HederaClient *client, struct HederaSigner *signer); + +/** + * Parse a Hedera `EntityId` from the passed string. + */ +enum HederaError hedera_entity_id_from_string(const char *s, + uint64_t *id_shard, + uint64_t *id_realm, + uint64_t *id_num); + +/** + * Execute this request against the provided client of the Hedera network. + */ +enum HederaError hedera_execute(const struct HederaClient *client, + const char *request, + const void *context, + void (*callback)(const void *context, enum HederaError err, const char *response)); + +/** + * Generates a new Ed25519 private key. + */ +struct HederaPrivateKey *hedera_private_key_generate_ed25519(void); + +/** + * Generates a new ECDSA(secp256k1) private key. + */ +struct HederaPrivateKey *hedera_private_key_generate_ecdsa_secp256k1(void); + +/** + * Gets the public key which corresponds to this private key. + */ +struct HederaPublicKey *hedera_private_key_get_public_key(struct HederaPrivateKey *key); + +/** + * Parse a Hedera private key from the passed string. + */ +enum HederaError hedera_private_key_from_string(const char *s, struct HederaPrivateKey **key); + +/** + * Format a Hedera private key as a string. + */ +const char *hedera_private_key_to_string(struct HederaPrivateKey *key); + +/** + * Releases memory associated with the private key. + */ +void hedera_private_key_free(struct HederaPrivateKey *key); + +/** + * Parse a Hedera public key from the passed string. + */ +enum HederaError hedera_public_key_from_string(const char *s, struct HederaPublicKey **key); + +/** + * Format a Hedera public key as a string. + */ +const char *hedera_public_key_to_string(struct HederaPublicKey *key); + +/** + * Releases memory associated with the public key. + */ +void hedera_public_key_free(struct HederaPublicKey *key); + +/** + * Create an opaque signer from a `HederaPrivateKey`. + */ +struct HederaSigner *hedera_signer_private_key(struct HederaPrivateKey *key); + +/** + * Subscribe with this request against the provided client of the Hedera network. + * On successful completion, calls `callback` with `ERROR_OK` and a `NULL` `message`. + */ +enum HederaError hedera_subscribe(const struct HederaClient *client, + const char *request, + const void *context, + void (*callback)(const void *context, enum HederaError err, const char *message)); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif /* _HEDERA_H */ diff --git a/sdk/go/native/linux/amd64/package.go b/sdk/go/native/linux/amd64/package.go new file mode 100644 index 00000000..f70035b9 --- /dev/null +++ b/sdk/go/native/linux/amd64/package.go @@ -0,0 +1 @@ +package amd64 diff --git a/sdk/go/native/linux/package.go b/sdk/go/native/linux/package.go new file mode 100644 index 00000000..d6216661 --- /dev/null +++ b/sdk/go/native/linux/package.go @@ -0,0 +1,3 @@ +package linux + +import _ "github.com/hashgraph/hedera-sdk-go/v3/native/linux/amd64" diff --git a/sdk/go/native/macos/amd64/package.go b/sdk/go/native/macos/amd64/package.go new file mode 100644 index 00000000..f70035b9 --- /dev/null +++ b/sdk/go/native/macos/amd64/package.go @@ -0,0 +1 @@ +package amd64 diff --git a/sdk/go/native/macos/arm64/package.go b/sdk/go/native/macos/arm64/package.go new file mode 100644 index 00000000..b3ae5cc3 --- /dev/null +++ b/sdk/go/native/macos/arm64/package.go @@ -0,0 +1 @@ +package arm64 diff --git a/sdk/go/native/macos/package.go b/sdk/go/native/macos/package.go new file mode 100644 index 00000000..6aa2b69f --- /dev/null +++ b/sdk/go/native/macos/package.go @@ -0,0 +1,6 @@ +package macos + +import ( + _ "github.com/hashgraph/hedera-sdk-go/v3/native/macos/amd64" + _ "github.com/hashgraph/hedera-sdk-go/v3/native/macos/arm64" +) diff --git a/sdk/go/native/package.go b/sdk/go/native/package.go new file mode 100644 index 00000000..fa6f3074 --- /dev/null +++ b/sdk/go/native/package.go @@ -0,0 +1,7 @@ +package native + +import ( + _ "github.com/hashgraph/hedera-sdk-go/v3/native/linux" + _ "github.com/hashgraph/hedera-sdk-go/v3/native/macos" + _ "github.com/hashgraph/hedera-sdk-go/v3/native/windows" +) diff --git a/sdk/go/native/windows/amd64/package.go b/sdk/go/native/windows/amd64/package.go new file mode 100644 index 00000000..f70035b9 --- /dev/null +++ b/sdk/go/native/windows/amd64/package.go @@ -0,0 +1 @@ +package amd64 diff --git a/sdk/go/native/windows/package.go b/sdk/go/native/windows/package.go new file mode 100644 index 00000000..2d46b8f1 --- /dev/null +++ b/sdk/go/native/windows/package.go @@ -0,0 +1,3 @@ +package windows + +import _ "github.com/hashgraph/hedera-sdk-go/v3/native/windows/amd64" diff --git a/sdk/go/public_key.go b/sdk/go/public_key.go new file mode 100644 index 00000000..e6b95c78 --- /dev/null +++ b/sdk/go/public_key.go @@ -0,0 +1,8 @@ +package hedera + +// PublicKey is an Ed25519 or ECDSA(secp256k1) public key on the Hedera network. +type PublicKey struct{} + +func (key PublicKey) _isKey() bool { + return true +} diff --git a/sdk/rust/Taskfile.yml b/sdk/rust/Taskfile.yml index cf8a2ff0..fe8d25e8 100644 --- a/sdk/rust/Taskfile.yml +++ b/sdk/rust/Taskfile.yml @@ -1,5 +1,7 @@ version: "3" +silent: true + tasks: build: run: once @@ -9,7 +11,7 @@ tasks: - src/**/*.rs cmds: # Build the Hedera Rust SDK (in debug mode) - - cargo build --message-format=short --features=ffi + - cmd: cargo build --message-format=short --features=ffi # Package for Swift - rm -rf ../swift/CHedera.xcframework/macos-*/ @@ -26,10 +28,17 @@ tasks: - mkdir -p ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/windows/amd64/ - mkdir -p ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/macos/{amd64,aarch64}/ - mkdir -p ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/linux/amd64/ - - cp -v target/debug/libhedera.so ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/linux/amd64/ 2> /dev/null || true - - cp -v target/debug/libhedera.dylib ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/macos/amd64/ 2> /dev/null || true - - cp -v target/debug/libhedera.dylib ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/macos/aarch64/ 2> /dev/null || true - - cp -v target/debug/hedera.dll ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/windows/amd64/ 2> /dev/null || true + - cp target/debug/libhedera.so ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/linux/amd64/ 2> /dev/null || true + - cp target/debug/libhedera.dylib ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/macos/amd64/ 2> /dev/null || true + - cp target/debug/libhedera.dylib ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/macos/aarch64/ 2> /dev/null || true + - cp target/debug/hedera.dll ../kotlin/src/main/resources/com/hedera/hashgraph/sdk/native/windows/amd64/ 2> /dev/null || true + + # Package for Go + - cp ../c/include/hedera.h ../go/native + - cp target/debug/libhedera.a ../go/native/linux/amd64/ 2> /dev/null || true + - cp target/debug/libhedera.a ../go/native/macos/amd64/ 2> /dev/null || true + - cp target/debug/libhedera.a ../go/native/macos/arm64/ 2> /dev/null || true + - cp target/debug/libhedera.a ../go/native/windows/amd64/ 2> /dev/null || true format: cmds: diff --git a/sdk/rust/src/key/key.rs b/sdk/rust/src/key/key.rs index b9b33e41..c85a934e 100644 --- a/sdk/rust/src/key/key.rs +++ b/sdk/rust/src/key/key.rs @@ -2,6 +2,7 @@ use hedera_proto::services; use crate::{ContractId, Error, FromProtobuf, PublicKey, ToProtobuf}; +/// Any method that can be used to authorize an operation on Hedera. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "camelCase")] pub enum Key {