Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wallet grpc stubs #144

Open
wants to merge 4 commits into
base: sigma
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ members = [
"core",
"wallet/macros",
"wallet/core",
"wallet/grpc/core",
"wallet/grpc/server",
"wallet/native",
"wallet/wasm",
"wallet/bip32",
Expand Down Expand Up @@ -125,6 +127,8 @@ kaspa-wallet-cli-wasm = { version = "0.16.0", path = "wallet/wasm" }
kaspa-wallet-keys = { version = "0.16.0", path = "wallet/keys" }
kaspa-wallet-pskt = { version = "0.16.0", path = "wallet/pskt" }
kaspa-wallet-core = { version = "0.16.0", path = "wallet/core" }
kaspa-wallet-grpc-core = { version = "0.16.0", path = "wallet/grpc/core" }
kaspa-wallet-grpc-server = { version = "0.16.0", path = "wallet/grpc/server" }
kaspa-wallet-macros = { version = "0.16.0", path = "wallet/macros" }
kaspa-wasm = { version = "0.16.0", path = "wasm" }
kaspa-wasm-core = { version = "0.16.0", path = "wasm/core" }
Expand Down
19 changes: 19 additions & 0 deletions wallet/grpc/core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "kaspa-wallet-grpc-core"
rust-version.workspace = true
version.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
edition.workspace = true
include.workspace = true

[dependencies]
tonic.workspace = true
prost.workspace = true

[lints]
workspace = true

[build-dependencies]
tonic-build = { workspace = true, features = ["prost"] }
9 changes: 9 additions & 0 deletions wallet/grpc/core/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use std::{io::Result, path::PathBuf};

fn main() -> Result<()> {
let proto_file = "./proto/kaspawalletd.proto";
let proto_dir = PathBuf::from("./proto");
tonic_build::configure().build_server(true).build_client(true).compile_protos(&[proto_file], &[proto_dir])?;
println!("cargo:rerun-if-changed={}", proto_file);
Ok(())
}
151 changes: 151 additions & 0 deletions wallet/grpc/core/proto/kaspawalletd.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
syntax = "proto3";

option go_package = "github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb";
package kaspawalletd;

service kaspawalletd {
rpc GetBalance(GetBalanceRequest) returns (GetBalanceResponse) {}
rpc GetExternalSpendableUTXOs(GetExternalSpendableUTXOsRequest)
returns (GetExternalSpendableUTXOsResponse) {}
rpc CreateUnsignedTransactions(CreateUnsignedTransactionsRequest)
returns (CreateUnsignedTransactionsResponse) {}
rpc ShowAddresses(ShowAddressesRequest) returns (ShowAddressesResponse) {}
rpc NewAddress(NewAddressRequest) returns (NewAddressResponse) {}
rpc Shutdown(ShutdownRequest) returns (ShutdownResponse) {}
rpc Broadcast(BroadcastRequest) returns (BroadcastResponse) {}
// BroadcastReplacement assumes that all transactions depend on the first one
rpc BroadcastReplacement(BroadcastRequest) returns (BroadcastResponse) {}
// Since SendRequest contains a password - this command should only be used on
// a trusted or secure connection
rpc Send(SendRequest) returns (SendResponse) {}
// Since SignRequest contains a password - this command should only be used on
// a trusted or secure connection
rpc Sign(SignRequest) returns (SignResponse) {}
rpc GetVersion(GetVersionRequest) returns (GetVersionResponse) {}
rpc BumpFee(BumpFeeRequest) returns (BumpFeeResponse) {}
}

message GetBalanceRequest {}

message GetBalanceResponse {
uint64 available = 1;
uint64 pending = 2;
repeated AddressBalances addressBalances = 3;
}

message AddressBalances {
string address = 1;
uint64 available = 2;
uint64 pending = 3;
}

message FeePolicy {
oneof feePolicy {
double maxFeeRate = 6;
double exactFeeRate = 7;
uint64 maxFee = 8;
}
}

message CreateUnsignedTransactionsRequest {
string address = 1;
uint64 amount = 2;
repeated string from = 3;
bool useExistingChangeAddress = 4;
bool isSendAll = 5;
FeePolicy feePolicy = 6;
}

message CreateUnsignedTransactionsResponse {
repeated bytes unsignedTransactions = 1;
}

message ShowAddressesRequest {}

message ShowAddressesResponse { repeated string address = 1; }

message NewAddressRequest {}

message NewAddressResponse { string address = 1; }

message BroadcastRequest {
bool isDomain = 1;
repeated bytes transactions = 2;
}

message BroadcastResponse { repeated string txIds = 1; }

message ShutdownRequest {}

message ShutdownResponse {}

message Outpoint {
string transactionId = 1;
uint32 index = 2;
}

message UtxosByAddressesEntry {
string address = 1;
Outpoint outpoint = 2;
UtxoEntry utxoEntry = 3;
}

message ScriptPublicKey {
uint32 version = 1;
string scriptPublicKey = 2;
}

message UtxoEntry {
uint64 amount = 1;
ScriptPublicKey scriptPublicKey = 2;
uint64 blockDaaScore = 3;
bool isCoinbase = 4;
}

message GetExternalSpendableUTXOsRequest { string address = 1; }

message GetExternalSpendableUTXOsResponse {
repeated UtxosByAddressesEntry Entries = 1;
}
// Since SendRequest contains a password - this command should only be used on a
// trusted or secure connection
message SendRequest {
string toAddress = 1;
uint64 amount = 2;
string password = 3;
repeated string from = 4;
bool useExistingChangeAddress = 5;
bool isSendAll = 6;
FeePolicy feePolicy = 7;
}

message SendResponse {
repeated string txIds = 1;
repeated bytes signedTransactions = 2;
}

// Since SignRequest contains a password - this command should only be used on a
// trusted or secure connection
message SignRequest {
repeated bytes unsignedTransactions = 1;
string password = 2;
}

message SignResponse { repeated bytes signedTransactions = 1; }

message GetVersionRequest {}

message GetVersionResponse { string version = 1; }

message BumpFeeRequest {
string password = 1;
repeated string from = 2;
bool useExistingChangeAddress = 3;
FeePolicy feePolicy = 4;
string txId = 5;
}

message BumpFeeResponse {
repeated bytes transactions = 1;
repeated string txIds = 2;
}
4 changes: 4 additions & 0 deletions wallet/grpc/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Include the generated proto types
pub mod kaspawalletd {
include!(concat!(env!("OUT_DIR"), "/kaspawalletd.rs"));
}
19 changes: 19 additions & 0 deletions wallet/grpc/server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "kaspa-wallet-grpc-server"
rust-version.workspace = true
version.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
edition.workspace = true
include.workspace = true

[dependencies]
kaspa-wallet-grpc-core.workspace = true
tonic.workspace = true

[dev-dependencies]
tokio = { workspace = true, features = ["macros", "test-util"] }

[lints]
workspace = true
123 changes: 123 additions & 0 deletions wallet/grpc/server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
use kaspa_wallet_grpc_core::kaspawalletd::{
kaspawalletd_server::Kaspawalletd, BroadcastRequest, BroadcastResponse, BumpFeeRequest, BumpFeeResponse,
CreateUnsignedTransactionsRequest, CreateUnsignedTransactionsResponse, GetBalanceRequest, GetBalanceResponse,
GetExternalSpendableUtxOsRequest, GetExternalSpendableUtxOsResponse, GetVersionRequest, GetVersionResponse, NewAddressRequest,
NewAddressResponse, SendRequest, SendResponse, ShowAddressesRequest, ShowAddressesResponse, ShutdownRequest, ShutdownResponse,
SignRequest, SignResponse,
};
use tonic::{Request, Response, Status};

#[derive(Debug, Default)]
pub struct KaspaWalletService {
// Add your service state here
}

#[tonic::async_trait]
impl Kaspawalletd for KaspaWalletService {
async fn get_balance(&self, _request: Request<GetBalanceRequest>) -> Result<Response<GetBalanceResponse>, Status> {
let response = GetBalanceResponse { available: 0, pending: 0, address_balances: vec![] };
Ok(Response::new(response))
}

async fn get_external_spendable_utx_os(
&self,
_request: Request<GetExternalSpendableUtxOsRequest>,
) -> Result<Response<GetExternalSpendableUtxOsResponse>, Status> {
let response = GetExternalSpendableUtxOsResponse { entries: vec![] };
Ok(Response::new(response))
}

async fn create_unsigned_transactions(
&self,
_request: Request<CreateUnsignedTransactionsRequest>,
) -> Result<Response<CreateUnsignedTransactionsResponse>, Status> {
let response = CreateUnsignedTransactionsResponse { unsigned_transactions: vec![] };
Ok(Response::new(response))
}

async fn show_addresses(&self, _request: Request<ShowAddressesRequest>) -> Result<Response<ShowAddressesResponse>, Status> {
let response = ShowAddressesResponse { address: vec![] };
Ok(Response::new(response))
}

async fn new_address(&self, _request: Request<NewAddressRequest>) -> Result<Response<NewAddressResponse>, Status> {
let response = NewAddressResponse { address: "".to_string() };
Ok(Response::new(response))
}

async fn shutdown(&self, _request: Request<ShutdownRequest>) -> Result<Response<ShutdownResponse>, Status> {
let response = ShutdownResponse {};
Ok(Response::new(response))
}

async fn broadcast(&self, _request: Request<BroadcastRequest>) -> Result<Response<BroadcastResponse>, Status> {
let response = BroadcastResponse { tx_ids: vec![] };
Ok(Response::new(response))
}

async fn broadcast_replacement(&self, _request: Request<BroadcastRequest>) -> Result<Response<BroadcastResponse>, Status> {
let response = BroadcastResponse { tx_ids: vec![] };
Ok(Response::new(response))
}

async fn send(&self, _request: Request<SendRequest>) -> Result<Response<SendResponse>, Status> {
let response = SendResponse { tx_ids: vec![], signed_transactions: vec![] };
Ok(Response::new(response))
}

async fn sign(&self, _request: Request<SignRequest>) -> Result<Response<SignResponse>, Status> {
let response = SignResponse { signed_transactions: vec![] };
Ok(Response::new(response))
}

async fn get_version(&self, _request: Request<GetVersionRequest>) -> Result<Response<GetVersionResponse>, Status> {
let response = GetVersionResponse { version: "".to_string() };
Ok(Response::new(response))
}

async fn bump_fee(&self, _request: Request<BumpFeeRequest>) -> Result<Response<BumpFeeResponse>, Status> {
let response = BumpFeeResponse { transactions: vec![], tx_ids: vec![] };
Ok(Response::new(response))
}
}

#[cfg(test)]
mod tests {
use super::*;
use kaspa_wallet_grpc_core::kaspawalletd::{
kaspawalletd_server::KaspawalletdServer, GetBalanceRequest, GetVersionRequest, NewAddressRequest,
};
use std::time::Duration;
use tonic::transport::Server;

#[tokio::test]
async fn test_server_basic_requests() {
// Start server
let addr = "[::1]:50051".parse().unwrap();
let service = KaspaWalletService::default();

let server_handle = tokio::spawn(async move {
Server::builder().add_service(KaspawalletdServer::new(service)).serve(addr).await.unwrap();
});
tokio::time::sleep(Duration::from_secs(1)).await; // wait until server starts
// Create client
let mut client = kaspa_wallet_grpc_core::kaspawalletd::kaspawalletd_client::KaspawalletdClient::connect("http://[::1]:50051")
.await
.unwrap();

// Test GetBalance
let balance = client.get_balance(GetBalanceRequest {}).await.unwrap();
assert_eq!(balance.get_ref().available, 0);
assert_eq!(balance.get_ref().pending, 0);

// Test GetVersion
let version = client.get_version(GetVersionRequest {}).await.unwrap();
assert_eq!(version.get_ref().version, "");

// Test NewAddress
let address = client.new_address(NewAddressRequest {}).await.unwrap();
assert_eq!(address.get_ref().address, "");

server_handle.abort();
}
}
Loading