syntax = "proto3";

package chain.gateway.v1;

option go_package = "github.com/tech/sendico/pkg/proto/gateway/chain/v1;chainv1";

import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
import "common/money/v1/money.proto";
import "common/pagination/v1/cursor.proto";
import "common/describable/v1/describable.proto";

// Supported blockchain networks for the managed wallets.
enum ChainNetwork {
  CHAIN_NETWORK_UNSPECIFIED = 0;
  CHAIN_NETWORK_ETHEREUM_MAINNET = 1;
  CHAIN_NETWORK_ARBITRUM_ONE = 2;
  CHAIN_NETWORK_TRON_MAINNET = 4;
  CHAIN_NETWORK_TRON_NILE = 5;
  CHAIN_NETWORK_ARBITRUM_SEPOLIA = 6;
}

enum ManagedWalletStatus {
  MANAGED_WALLET_STATUS_UNSPECIFIED = 0;
  MANAGED_WALLET_ACTIVE = 1;
  MANAGED_WALLET_SUSPENDED = 2;
  MANAGED_WALLET_CLOSED = 3;
}

enum DepositStatus {
  DEPOSIT_STATUS_UNSPECIFIED = 0;
  DEPOSIT_PENDING = 1;
  DEPOSIT_CONFIRMED = 2;
  DEPOSIT_FAILED = 3;
}

enum TransferStatus {
  TRANSFER_STATUS_UNSPECIFIED = 0;

  TRANSFER_CREATED    = 1; // record exists, not started
  TRANSFER_PROCESSING = 2; // we are working on it (signing, building tx, etc)
  TRANSFER_WAITING    = 3; // waiting external world (network/provider)

  TRANSFER_SUCCESS    = 4; // final success
  TRANSFER_FAILED     = 5; // final failure
  TRANSFER_CANCELLED  = 6; // final cancelled
}


// Asset captures the chain/token pair so downstream systems can route correctly.
message Asset {
  ChainNetwork chain = 1;
  string token_symbol = 2;
  string contract_address = 3; // optional override when multiple contracts exist per chain
}

message ManagedWallet {
  string wallet_ref = 1;
  string organization_ref = 2;
  string owner_ref = 3;
  Asset asset = 4;
  string deposit_address = 5;
  ManagedWalletStatus status = 6;
  map<string, string> metadata = 7;
  google.protobuf.Timestamp created_at = 8;
  google.protobuf.Timestamp updated_at = 9;
  common.describable.v1.Describable describable = 10;
}

message CreateManagedWalletRequest {
  string idempotency_key = 1;
  string organization_ref = 2;
  string owner_ref = 3;
  Asset asset = 4;
  map<string, string> metadata = 5;
  common.describable.v1.Describable describable = 6;
}

message CreateManagedWalletResponse {
  ManagedWallet wallet = 1;
}

message GetManagedWalletRequest {
  string wallet_ref = 1;
}

message GetManagedWalletResponse {
  ManagedWallet wallet = 1;
}

message ListManagedWalletsRequest {
  string organization_ref = 1;
  reserved 2;
  reserved "owner_ref";
  Asset asset = 3;
  common.pagination.v1.CursorPageRequest page = 4;
  // Optional owner filter with 3-state semantics:
  // - not set: return all wallets within organization
  // - set to empty string: return wallets where owner_ref is null/empty
  // - set to a value: return wallets where owner_ref matches
  google.protobuf.StringValue owner_ref_filter = 5;
}

message ListManagedWalletsResponse {
  repeated ManagedWallet wallets = 1;
  common.pagination.v1.CursorPageResponse page = 2;
}

message WalletBalance {
  common.money.v1.Money available = 1;
  common.money.v1.Money pending_inbound = 2;
  common.money.v1.Money pending_outbound = 3;
  google.protobuf.Timestamp calculated_at = 4;
  common.money.v1.Money native_available = 5;
}

message GetWalletBalanceRequest {
  string wallet_ref = 1;
}

message GetWalletBalanceResponse {
  WalletBalance balance = 1;
}

message ServiceFeeBreakdown {
  string fee_code = 1;
  common.money.v1.Money amount = 2;
  string description = 3;
}

message TransferDestination {
  oneof destination {
    string managed_wallet_ref = 1;
    string external_address = 2;
  }
  string memo = 3; // chain-specific memo/tag when required by the destination
}

message Transfer {
  string transfer_ref = 1;
  string idempotency_key = 2;
  string organization_ref = 3;
  string source_wallet_ref = 4;
  TransferDestination destination = 5;
  Asset asset = 6;
  common.money.v1.Money requested_amount = 7;
  common.money.v1.Money net_amount = 8;
  repeated ServiceFeeBreakdown fees = 9;
  TransferStatus status = 10;
  string transaction_hash = 11;
  string failure_reason = 12;
  google.protobuf.Timestamp created_at = 13;
  google.protobuf.Timestamp updated_at = 14;
  string intent_ref = 15;
  string payment_ref = 16;
  string operation_ref = 17;
}

message SubmitTransferRequest {
  string idempotency_key = 1;
  string organization_ref = 2;
  string source_wallet_ref = 3;
  TransferDestination destination = 4;
  common.money.v1.Money amount = 5;
  repeated ServiceFeeBreakdown fees = 6;
  map<string, string> metadata = 7;
  string operation_ref = 8;
  string intent_ref = 9;
  string payment_ref = 10;
}

message SubmitTransferResponse {
  Transfer transfer = 1;
}

message GetTransferRequest {
  string transfer_ref = 1;
}

message GetTransferResponse {
  Transfer transfer = 1;
}

message ListTransfersRequest {
  string source_wallet_ref = 1;
  string destination_wallet_ref = 2;
  TransferStatus status = 3;
  common.pagination.v1.CursorPageRequest page = 4;
}

message ListTransfersResponse {
  repeated Transfer transfers = 1;
  common.pagination.v1.CursorPageResponse page = 2;
}

message EstimateTransferFeeRequest {
  string source_wallet_ref = 1;
  TransferDestination destination = 2;
  common.money.v1.Money amount = 3;
  Asset asset = 4;
}

message EstimateTransferFeeResponse {
  common.money.v1.Money network_fee = 1;
  string estimation_context = 2;
}

message ComputeGasTopUpRequest {
  string wallet_ref = 1;
  common.money.v1.Money estimated_total_fee = 2;
}

message ComputeGasTopUpResponse {
  common.money.v1.Money topup_amount = 1;
  bool cap_hit = 2;
}

message EnsureGasTopUpRequest {
  string idempotency_key = 1;
  string organization_ref = 2;
  string source_wallet_ref = 3;
  string target_wallet_ref = 4;
  common.money.v1.Money estimated_total_fee = 5;
  map<string, string> metadata = 6;
  string payment_ref = 7;
  string intent_ref = 8;
  string operation_ref = 9;
}

message EnsureGasTopUpResponse {
  common.money.v1.Money topup_amount = 1;
  bool cap_hit = 2;
  Transfer transfer = 3;
}

message WalletDepositObservedEvent {
  string deposit_ref = 1;
  string wallet_ref = 2;
  Asset asset = 3;
  common.money.v1.Money amount = 4;
  string source_address = 5;
  string transaction_hash = 6;
  string block_id = 7;
  DepositStatus status = 8;
  google.protobuf.Timestamp observed_at = 9;
}

message TransferStatusChangedEvent {
  Transfer transfer = 1;
  string reason = 2;             
}
