service backend
This commit is contained in:
7
api/proto/account_created.proto
Normal file
7
api/proto/account_created.proto
Normal file
@@ -0,0 +1,7 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/generated/gmessaging";
|
||||
|
||||
message AccountCreatedEvent {
|
||||
string AccountRef = 1;
|
||||
}
|
||||
161
api/proto/billing/fees/v1/fees.proto
Normal file
161
api/proto/billing/fees/v1/fees.proto
Normal file
@@ -0,0 +1,161 @@
|
||||
// fees/v1/fees.proto
|
||||
syntax = "proto3";
|
||||
package fees.v1;
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/proto/billing/fees/v1;feesv1";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "common/money/v1/money.proto";
|
||||
import "common/fx/v1/fx.proto";
|
||||
import "common/accounting/v1/posting.proto";
|
||||
import "common/trace/v1/trace.proto";
|
||||
|
||||
// --------------------
|
||||
// Core business enums
|
||||
// --------------------
|
||||
enum Trigger {
|
||||
TRIGGER_UNSPECIFIED = 0;
|
||||
TRIGGER_CAPTURE = 1;
|
||||
TRIGGER_REFUND = 2;
|
||||
TRIGGER_DISPUTE = 3;
|
||||
TRIGGER_PAYOUT = 4;
|
||||
TRIGGER_FX_CONVERSION = 5;
|
||||
}
|
||||
|
||||
// What to do if net-payable is insufficient to collect fees now.
|
||||
enum InsufficientNetPolicy {
|
||||
INSUFFICIENT_NET_UNSPECIFIED = 0;
|
||||
BLOCK_POSTING = 1; // fail the request
|
||||
SWEEP_ORG_CASH = 2; // charge an org cash account
|
||||
INVOICE_LATER = 3; // return zero lines; AR later
|
||||
}
|
||||
|
||||
// Optional per-call overrides (rare).
|
||||
message PolicyOverrides {
|
||||
InsufficientNetPolicy insufficient_net = 1;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// Request/response meta
|
||||
// --------------------
|
||||
message RequestMeta {
|
||||
string organization_ref = 1; // org scope; tenant resolved internally
|
||||
common.trace.v1.TraceContext trace = 2;
|
||||
}
|
||||
|
||||
message ResponseMeta {
|
||||
common.trace.v1.TraceContext trace = 1;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// Intent & outputs
|
||||
// --------------------
|
||||
|
||||
// What the ledger/PO intends to do; used to select plan rules.
|
||||
message Intent {
|
||||
Trigger trigger = 1;
|
||||
common.money.v1.Money base_amount = 2; // fee base (e.g., captured gross)
|
||||
google.protobuf.Timestamp booked_at = 3; // for effective-dated plan
|
||||
string origin_type = 4; // e.g., "charge.capture"
|
||||
string origin_ref = 5; // gateway or business id
|
||||
map<string,string> attributes = 6; // e.g., mcc, card_present, country
|
||||
}
|
||||
|
||||
// FX details actually used during fee calc (if any).
|
||||
message FXUsed {
|
||||
common.fx.v1.CurrencyPair pair = 1;
|
||||
common.fx.v1.Side side = 2;
|
||||
common.money.v1.Decimal rate = 3; // applied rate
|
||||
int64 asof_unix_ms = 4; // source timestamp (ms)
|
||||
string provider = 5; // e.g., "ECB", "XE"
|
||||
string rate_ref = 6; // provider ref/id
|
||||
common.money.v1.Decimal spread_bps = 7; // applied spread
|
||||
}
|
||||
|
||||
// A derived posting line ready for the ledger to post as-is.
|
||||
message DerivedPostingLine {
|
||||
string ledger_account_ref = 1; // resolved account
|
||||
common.money.v1.Money money = 2; // amount/currency
|
||||
common.accounting.v1.PostingLineType line_type = 3; // FEE/TAX/SPREAD/REVERSAL
|
||||
common.accounting.v1.EntrySide side = 4; // DEBIT/CREDIT
|
||||
map<string,string> meta = 5; // fee_rule_id, rule_version, tax_code, tax_rate, fx_rate_used, etc.
|
||||
}
|
||||
|
||||
// Snapshot of rules applied for audit/replay.
|
||||
message AppliedRule {
|
||||
string rule_id = 1;
|
||||
string rule_version = 2;
|
||||
string formula = 3; // e.g., "2.90% + 0.30 (min 0.50)"
|
||||
common.money.v1.RoundingMode rounding = 4;
|
||||
string tax_code = 5; // if applicable
|
||||
string tax_rate = 6; // decimal string
|
||||
map<string,string> parameters = 7; // thresholds, tiers, etc.
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// RPC: synchronous quote for posting
|
||||
// --------------------
|
||||
message QuoteFeesRequest {
|
||||
RequestMeta meta = 1;
|
||||
Intent intent = 2;
|
||||
PolicyOverrides policy = 3;
|
||||
}
|
||||
|
||||
message QuoteFeesResponse {
|
||||
ResponseMeta meta = 1;
|
||||
repeated DerivedPostingLine lines = 2; // derived fee/tax/spread lines
|
||||
repeated AppliedRule applied = 3; // rules snapshot
|
||||
FXUsed fx_used = 4; // optional if FX participated
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// RPC: pre-pricing (UI/PO) with signed token
|
||||
// --------------------
|
||||
message PrecomputeFeesRequest {
|
||||
RequestMeta meta = 1;
|
||||
Intent intent = 2;
|
||||
int64 ttl_ms = 3; // token validity window
|
||||
}
|
||||
|
||||
message PrecomputeFeesResponse {
|
||||
ResponseMeta meta = 1;
|
||||
string fee_quote_token = 2; // opaque, signed
|
||||
google.protobuf.Timestamp expires_at = 3;
|
||||
// Optional preview so UI can render exact numbers now:
|
||||
repeated DerivedPostingLine lines = 4;
|
||||
repeated AppliedRule applied = 5;
|
||||
FXUsed fx_used = 6;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// RPC: validate/decode a token before posting
|
||||
// --------------------
|
||||
message ValidateFeeTokenRequest {
|
||||
RequestMeta meta = 1;
|
||||
string fee_quote_token = 2;
|
||||
}
|
||||
|
||||
message ValidateFeeTokenResponse {
|
||||
ResponseMeta meta = 1;
|
||||
bool valid = 2;
|
||||
string reason = 3; // if invalid
|
||||
// If valid, return normalized content embedded in the token:
|
||||
Intent intent = 4;
|
||||
repeated DerivedPostingLine lines = 5;
|
||||
repeated AppliedRule applied = 6;
|
||||
FXUsed fx_used = 7;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// Service
|
||||
// --------------------
|
||||
service FeeEngine {
|
||||
// Compute derived fee/tax/spread lines for immediate posting.
|
||||
rpc QuoteFees (QuoteFeesRequest) returns (QuoteFeesResponse);
|
||||
|
||||
// Pre-price for UX/PO and return a signed token to post later.
|
||||
rpc PrecomputeFees (PrecomputeFeesRequest) returns (PrecomputeFeesResponse);
|
||||
|
||||
// Verify/expand a token just before posting (prevents policy drift).
|
||||
rpc ValidateFeeToken (ValidateFeeTokenRequest) returns (ValidateFeeTokenResponse);
|
||||
}
|
||||
216
api/proto/chain/gateway/v1/gateway.proto
Normal file
216
api/proto/chain/gateway/v1/gateway.proto
Normal file
@@ -0,0 +1,216 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package chain.gateway.v1;
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/proto/chain/gateway/v1;gatewayv1";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "common/money/v1/money.proto";
|
||||
import "common/pagination/v1/cursor.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_OTHER_EVM = 3;
|
||||
}
|
||||
|
||||
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_PENDING = 1;
|
||||
TRANSFER_SIGNING = 2;
|
||||
TRANSFER_SUBMITTED = 3;
|
||||
TRANSFER_CONFIRMED = 4;
|
||||
TRANSFER_FAILED = 5;
|
||||
TRANSFER_CANCELLED = 6;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
message CreateManagedWalletRequest {
|
||||
string idempotency_key = 1;
|
||||
string organization_ref = 2;
|
||||
string owner_ref = 3;
|
||||
Asset asset = 4;
|
||||
map<string, string> metadata = 5;
|
||||
}
|
||||
|
||||
message CreateManagedWalletResponse {
|
||||
ManagedWallet wallet = 1;
|
||||
}
|
||||
|
||||
message GetManagedWalletRequest {
|
||||
string wallet_ref = 1;
|
||||
}
|
||||
|
||||
message GetManagedWalletResponse {
|
||||
ManagedWallet wallet = 1;
|
||||
}
|
||||
|
||||
message ListManagedWalletsRequest {
|
||||
string organization_ref = 1;
|
||||
string owner_ref = 2;
|
||||
Asset asset = 3;
|
||||
common.pagination.v1.CursorPageRequest page = 4;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 client_reference = 8;
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
service ChainGatewayService {
|
||||
rpc CreateManagedWallet(CreateManagedWalletRequest) returns (CreateManagedWalletResponse);
|
||||
rpc GetManagedWallet(GetManagedWalletRequest) returns (GetManagedWalletResponse);
|
||||
rpc ListManagedWallets(ListManagedWalletsRequest) returns (ListManagedWalletsResponse);
|
||||
|
||||
rpc GetWalletBalance(GetWalletBalanceRequest) returns (GetWalletBalanceResponse);
|
||||
|
||||
rpc SubmitTransfer(SubmitTransferRequest) returns (SubmitTransferResponse);
|
||||
rpc GetTransfer(GetTransferRequest) returns (GetTransferResponse);
|
||||
rpc ListTransfers(ListTransfersRequest) returns (ListTransfersResponse);
|
||||
|
||||
rpc EstimateTransferFee(EstimateTransferFeeRequest) returns (EstimateTransferFeeResponse);
|
||||
}
|
||||
19
api/proto/common/accounting/v1/posting.proto
Normal file
19
api/proto/common/accounting/v1/posting.proto
Normal file
@@ -0,0 +1,19 @@
|
||||
syntax = "proto3";
|
||||
package common.accounting.v1;
|
||||
option go_package = "github.com/tech/sendico/pkg/proto/common/accounting/v1;accountingv1";
|
||||
|
||||
// Direction on a line; safe to share.
|
||||
enum EntrySide {
|
||||
ENTRY_SIDE_UNSPECIFIED = 0;
|
||||
ENTRY_SIDE_DEBIT = 1;
|
||||
ENTRY_SIDE_CREDIT = 2;
|
||||
}
|
||||
|
||||
// Generic line semantics used across services for derived lines.
|
||||
enum PostingLineType {
|
||||
POSTING_LINE_TYPE_UNSPECIFIED = 0;
|
||||
POSTING_LINE_FEE = 1;
|
||||
POSTING_LINE_TAX = 2;
|
||||
POSTING_LINE_SPREAD = 3;
|
||||
POSTING_LINE_REVERSAL = 4;
|
||||
}
|
||||
14
api/proto/common/fx/v1/fx.proto
Normal file
14
api/proto/common/fx/v1/fx.proto
Normal file
@@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
package common.fx.v1;
|
||||
option go_package = "github.com/tech/sendico/pkg/proto/common/fx/v1;fxv1";
|
||||
|
||||
message CurrencyPair {
|
||||
string base = 1;
|
||||
string quote = 2;
|
||||
}
|
||||
|
||||
enum Side {
|
||||
SIDE_UNSPECIFIED = 0;
|
||||
BUY_BASE_SELL_QUOTE = 1;
|
||||
SELL_BASE_BUY_QUOTE = 2;
|
||||
}
|
||||
23
api/proto/common/money/v1/money.proto
Normal file
23
api/proto/common/money/v1/money.proto
Normal file
@@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
package common.money.v1;
|
||||
option go_package = "github.com/tech/sendico/pkg/proto/common/money/v1;moneyv1";
|
||||
|
||||
message Decimal { string value = 1; } // exact decimal as string
|
||||
|
||||
message Money {
|
||||
string amount = 1; // decimal string
|
||||
string currency = 2; // ISO 4217 or your code set
|
||||
}
|
||||
|
||||
enum RoundingMode {
|
||||
ROUNDING_MODE_UNSPECIFIED = 0;
|
||||
ROUND_HALF_EVEN = 1;
|
||||
ROUND_HALF_UP = 2;
|
||||
ROUND_DOWN = 3;
|
||||
}
|
||||
|
||||
message CurrencyMeta {
|
||||
string code = 1;
|
||||
uint32 decimals = 2;
|
||||
RoundingMode rounding = 3;
|
||||
}
|
||||
12
api/proto/common/pagination/v1/cursor.proto
Normal file
12
api/proto/common/pagination/v1/cursor.proto
Normal file
@@ -0,0 +1,12 @@
|
||||
syntax = "proto3";
|
||||
package common.pagination.v1;
|
||||
option go_package = "github.com/tech/sendico/pkg/proto/common/pagination/v1;paginationv1";
|
||||
|
||||
message CursorPageRequest {
|
||||
string cursor = 1; // opaque
|
||||
int32 limit = 2; // page size
|
||||
}
|
||||
|
||||
message CursorPageResponse {
|
||||
string next_cursor = 1; // opaque
|
||||
}
|
||||
9
api/proto/common/trace/v1/trace.proto
Normal file
9
api/proto/common/trace/v1/trace.proto
Normal file
@@ -0,0 +1,9 @@
|
||||
syntax = "proto3";
|
||||
package common.trace.v1;
|
||||
option go_package = "github.com/tech/sendico/pkg/proto/common/trace/v1;tracev1";
|
||||
|
||||
message TraceContext {
|
||||
string request_ref = 1;
|
||||
string idempotency_key = 2;
|
||||
string trace_ref = 3;
|
||||
}
|
||||
22
api/proto/envelope.proto
Normal file
22
api/proto/envelope.proto
Normal file
@@ -0,0 +1,22 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/generated/gmessaging";
|
||||
|
||||
message NotificationEvent {
|
||||
string type = 1; // NotificationType
|
||||
string action = 2; // NotificationAction
|
||||
}
|
||||
|
||||
message EventMetadata {
|
||||
string sender = 1;
|
||||
string message_id = 2;
|
||||
google.protobuf.Timestamp timestamp = 3;
|
||||
}
|
||||
|
||||
message Envelope {
|
||||
NotificationEvent event = 2; // Notification event with type and action
|
||||
bytes message_data = 3; // Serialized Protobuf message data
|
||||
EventMetadata metadata = 4; // Metadata about the event
|
||||
}
|
||||
194
api/proto/ledger/v1/ledger.proto
Normal file
194
api/proto/ledger/v1/ledger.proto
Normal file
@@ -0,0 +1,194 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package ledger.v1;
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/proto/ledger/v1;ledgerv1";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "common/money/v1/money.proto";
|
||||
|
||||
// ===== Enums =====
|
||||
|
||||
enum EntryType {
|
||||
ENTRY_TYPE_UNSPECIFIED = 0;
|
||||
ENTRY_CREDIT = 1;
|
||||
ENTRY_DEBIT = 2;
|
||||
ENTRY_TRANSFER = 3;
|
||||
ENTRY_FX = 4;
|
||||
ENTRY_FEE = 5;
|
||||
ENTRY_ADJUST = 6;
|
||||
ENTRY_REVERSE = 7;
|
||||
}
|
||||
|
||||
enum LineType {
|
||||
LINE_TYPE_UNSPECIFIED = 0;
|
||||
LINE_MAIN = 1;
|
||||
LINE_FEE = 2;
|
||||
LINE_SPREAD = 3;
|
||||
LINE_REVERSAL = 4;
|
||||
}
|
||||
|
||||
enum AccountType {
|
||||
ACCOUNT_TYPE_UNSPECIFIED = 0;
|
||||
ACCOUNT_TYPE_ASSET = 1;
|
||||
ACCOUNT_TYPE_LIABILITY = 2;
|
||||
ACCOUNT_TYPE_REVENUE = 3;
|
||||
ACCOUNT_TYPE_EXPENSE = 4;
|
||||
}
|
||||
|
||||
enum AccountStatus {
|
||||
ACCOUNT_STATUS_UNSPECIFIED = 0;
|
||||
ACCOUNT_STATUS_ACTIVE = 1;
|
||||
ACCOUNT_STATUS_FROZEN = 2;
|
||||
}
|
||||
|
||||
// LedgerAccount captures the canonical representation of an account resource.
|
||||
message LedgerAccount {
|
||||
string ledger_account_ref = 1;
|
||||
string organization_ref = 2;
|
||||
string account_code = 3;
|
||||
AccountType account_type = 4;
|
||||
string currency = 5;
|
||||
AccountStatus status = 6;
|
||||
bool allow_negative = 7;
|
||||
bool is_settlement = 8;
|
||||
map<string, string> metadata = 9;
|
||||
google.protobuf.Timestamp created_at = 10;
|
||||
google.protobuf.Timestamp updated_at = 11;
|
||||
}
|
||||
|
||||
// A single posting line (mirrors your PostingLine model)
|
||||
message PostingLine {
|
||||
string ledger_account_ref = 1;
|
||||
common.money.v1.Money money = 2;
|
||||
LineType line_type = 3; // MAIN, FEE, SPREAD, ...
|
||||
}
|
||||
|
||||
// ===== Requests/Responses =====
|
||||
|
||||
service LedgerService {
|
||||
rpc CreateAccount (CreateAccountRequest) returns (CreateAccountResponse);
|
||||
|
||||
rpc PostCreditWithCharges (PostCreditRequest) returns (PostResponse);
|
||||
rpc PostDebitWithCharges (PostDebitRequest) returns (PostResponse);
|
||||
rpc TransferInternal (TransferRequest) returns (PostResponse);
|
||||
rpc ApplyFXWithCharges (FXRequest) returns (PostResponse);
|
||||
|
||||
rpc GetBalance (GetBalanceRequest) returns (BalanceResponse);
|
||||
rpc GetJournalEntry (GetEntryRequest) returns (JournalEntryResponse);
|
||||
rpc GetStatement (GetStatementRequest) returns (StatementResponse);
|
||||
}
|
||||
|
||||
message CreateAccountRequest {
|
||||
string organization_ref = 1;
|
||||
string account_code = 2;
|
||||
AccountType account_type = 3;
|
||||
string currency = 4;
|
||||
AccountStatus status = 5;
|
||||
bool allow_negative = 6;
|
||||
bool is_settlement = 7;
|
||||
map<string, string> metadata = 8;
|
||||
}
|
||||
|
||||
message CreateAccountResponse {
|
||||
LedgerAccount account = 1;
|
||||
}
|
||||
|
||||
// Common: optional event_time lets caller set business time; server may default to now.
|
||||
message PostCreditRequest {
|
||||
string idempotency_key = 1;
|
||||
string organization_ref = 2; // aligns with PermissionBound
|
||||
string ledger_account_ref = 3;
|
||||
common.money.v1.Money money = 4;
|
||||
string description = 5;
|
||||
repeated PostingLine charges = 6; // FEE/SPREAD lines (no MAIN here)
|
||||
map<string, string> metadata = 7;
|
||||
google.protobuf.Timestamp event_time = 8;
|
||||
string contra_ledger_account_ref = 9; // optional override for settlement/contra account
|
||||
}
|
||||
|
||||
message PostDebitRequest {
|
||||
string idempotency_key = 1;
|
||||
string organization_ref = 2;
|
||||
string ledger_account_ref = 3;
|
||||
common.money.v1.Money money = 4;
|
||||
string description = 5;
|
||||
repeated PostingLine charges = 6; // FEE/SPREAD
|
||||
map<string, string> metadata = 7;
|
||||
google.protobuf.Timestamp event_time = 8;
|
||||
string contra_ledger_account_ref = 9; // optional override for settlement/contra account
|
||||
}
|
||||
|
||||
message TransferRequest {
|
||||
string idempotency_key = 1;
|
||||
string organization_ref = 2;
|
||||
string from_ledger_account_ref = 3;
|
||||
string to_ledger_account_ref = 4;
|
||||
common.money.v1.Money money = 5; // transfer amount/currency
|
||||
string description = 6;
|
||||
repeated PostingLine charges = 7; // optional FEE/SPREAD lines
|
||||
map<string, string> metadata = 8;
|
||||
google.protobuf.Timestamp event_time = 9;
|
||||
}
|
||||
|
||||
message FXRequest {
|
||||
string idempotency_key = 1;
|
||||
string organization_ref = 2;
|
||||
string from_ledger_account_ref = 3;
|
||||
string to_ledger_account_ref = 4;
|
||||
|
||||
common.money.v1.Money from_money = 5; // debited
|
||||
common.money.v1.Money to_money = 6; // credited
|
||||
string rate = 7; // quoted rate as string (snapshot for audit)
|
||||
|
||||
string description = 8;
|
||||
repeated PostingLine charges = 9; // FEE/SPREAD lines
|
||||
map<string, string> metadata = 10;
|
||||
google.protobuf.Timestamp event_time = 11;
|
||||
}
|
||||
|
||||
message PostResponse {
|
||||
string journal_entry_ref = 1;
|
||||
int64 version = 2; // ledger's entry version (monotonic per scope)
|
||||
EntryType entry_type = 3;
|
||||
}
|
||||
|
||||
// ---- Balances & Entries ----
|
||||
|
||||
message GetBalanceRequest {
|
||||
string ledger_account_ref = 1;
|
||||
}
|
||||
|
||||
message BalanceResponse {
|
||||
string ledger_account_ref = 1;
|
||||
common.money.v1.Money balance = 2;
|
||||
int64 version = 3;
|
||||
google.protobuf.Timestamp last_updated = 4;
|
||||
}
|
||||
|
||||
message GetEntryRequest {
|
||||
string entry_ref = 1;
|
||||
}
|
||||
|
||||
message JournalEntryResponse {
|
||||
string entry_ref = 1;
|
||||
string idempotency_key = 2;
|
||||
EntryType entry_type = 3;
|
||||
string description = 4;
|
||||
google.protobuf.Timestamp event_time = 5;
|
||||
int64 version = 6;
|
||||
repeated PostingLine lines = 7;
|
||||
map<string, string> metadata = 8;
|
||||
repeated string ledger_account_refs = 9; // denormalized set for client-side filtering
|
||||
}
|
||||
|
||||
message GetStatementRequest {
|
||||
string ledger_account_ref = 1;
|
||||
string cursor = 2; // opaque
|
||||
int32 limit = 3; // page size
|
||||
}
|
||||
|
||||
message StatementResponse {
|
||||
repeated JournalEntryResponse entries = 1;
|
||||
string next_cursor = 2;
|
||||
}
|
||||
13
api/proto/notification_sent.proto
Normal file
13
api/proto/notification_sent.proto
Normal file
@@ -0,0 +1,13 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/generated/gmessaging";
|
||||
|
||||
import "operation_result.proto";
|
||||
|
||||
message NotificationSentEvent {
|
||||
string UserID = 1;
|
||||
string TemplateID = 2;
|
||||
string Channel = 3;
|
||||
string Locale = 4;
|
||||
OperationResult Status = 5;
|
||||
}
|
||||
8
api/proto/object_updated.proto
Normal file
8
api/proto/object_updated.proto
Normal file
@@ -0,0 +1,8 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/generated/gmessaging";
|
||||
|
||||
message ObjectUpdatedEvent {
|
||||
string ObjectRef = 1;
|
||||
string ActorAccountRef = 2;
|
||||
}
|
||||
8
api/proto/operation_result.proto
Normal file
8
api/proto/operation_result.proto
Normal file
@@ -0,0 +1,8 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/generated/gmessaging";
|
||||
|
||||
message OperationResult {
|
||||
bool IsSuccessful = 1;
|
||||
string ErrorDescription = 2;
|
||||
}
|
||||
125
api/proto/oracle/v1/oracle.proto
Normal file
125
api/proto/oracle/v1/oracle.proto
Normal file
@@ -0,0 +1,125 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package oracle.v1;
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/proto/oracle/v1;oraclev1";
|
||||
|
||||
import "common/money/v1/money.proto";
|
||||
import "common/fx/v1/fx.proto";
|
||||
import "common/trace/v1/trace.proto";
|
||||
|
||||
message RateSnapshot {
|
||||
common.fx.v1.CurrencyPair pair = 1;
|
||||
common.money.v1.Decimal mid = 2;
|
||||
common.money.v1.Decimal bid = 3;
|
||||
common.money.v1.Decimal ask = 4;
|
||||
int64 asof_unix_ms = 5;
|
||||
string provider = 6;
|
||||
string rate_ref = 7;
|
||||
common.money.v1.Decimal spread_bps = 8;
|
||||
}
|
||||
|
||||
message RequestMeta {
|
||||
string request_ref = 1 [deprecated = true];
|
||||
string tenant_ref = 2;
|
||||
string organization_ref = 3;
|
||||
string idempotency_key = 4 [deprecated = true];
|
||||
string trace_ref = 5 [deprecated = true];
|
||||
common.trace.v1.TraceContext trace = 6;
|
||||
}
|
||||
|
||||
message ResponseMeta {
|
||||
string request_ref = 1 [deprecated = true];
|
||||
string trace_ref = 2 [deprecated = true];
|
||||
common.trace.v1.TraceContext trace = 3;
|
||||
}
|
||||
|
||||
message Quote {
|
||||
string quote_ref = 1;
|
||||
common.fx.v1.CurrencyPair pair = 2;
|
||||
common.fx.v1.Side side = 3;
|
||||
common.money.v1.Decimal price = 4;
|
||||
common.money.v1.Money base_amount = 5;
|
||||
common.money.v1.Money quote_amount = 6;
|
||||
int64 expires_at_unix_ms = 7;
|
||||
string provider = 8;
|
||||
string rate_ref = 9;
|
||||
bool firm = 10;
|
||||
}
|
||||
|
||||
message GetQuoteRequest {
|
||||
RequestMeta meta = 1;
|
||||
common.fx.v1.CurrencyPair pair = 2;
|
||||
common.fx.v1.Side side = 3;
|
||||
oneof amount_input {
|
||||
common.money.v1.Money base_amount = 4;
|
||||
common.money.v1.Money quote_amount = 5;
|
||||
}
|
||||
bool firm = 6;
|
||||
int64 ttl_ms = 7;
|
||||
string preferred_provider = 8;
|
||||
int32 max_age_ms = 9;
|
||||
}
|
||||
|
||||
message GetQuoteResponse {
|
||||
ResponseMeta meta = 1;
|
||||
Quote quote = 2;
|
||||
}
|
||||
|
||||
message ValidateQuoteRequest {
|
||||
RequestMeta meta = 1;
|
||||
string quote_ref = 2;
|
||||
}
|
||||
|
||||
message ValidateQuoteResponse {
|
||||
ResponseMeta meta = 1;
|
||||
Quote quote = 2;
|
||||
bool valid = 3;
|
||||
string reason = 4;
|
||||
}
|
||||
|
||||
message ConsumeQuoteRequest {
|
||||
RequestMeta meta = 1;
|
||||
string quote_ref = 2;
|
||||
string ledger_txn_ref = 3;
|
||||
}
|
||||
|
||||
message ConsumeQuoteResponse {
|
||||
ResponseMeta meta = 1;
|
||||
bool consumed = 2;
|
||||
string reason = 3;
|
||||
}
|
||||
|
||||
message LatestRateRequest {
|
||||
RequestMeta meta = 1;
|
||||
common.fx.v1.CurrencyPair pair = 2;
|
||||
string provider = 3;
|
||||
}
|
||||
|
||||
message LatestRateResponse {
|
||||
ResponseMeta meta = 1;
|
||||
RateSnapshot rate = 2;
|
||||
}
|
||||
|
||||
message ListPairsRequest {
|
||||
RequestMeta meta = 1;
|
||||
}
|
||||
|
||||
message PairMeta {
|
||||
common.fx.v1.CurrencyPair pair = 1;
|
||||
common.money.v1.CurrencyMeta base_meta = 2;
|
||||
common.money.v1.CurrencyMeta quote_meta = 3;
|
||||
}
|
||||
|
||||
message ListPairsResponse {
|
||||
ResponseMeta meta = 1;
|
||||
repeated PairMeta pairs = 2;
|
||||
}
|
||||
|
||||
service Oracle {
|
||||
rpc GetQuote(GetQuoteRequest) returns (GetQuoteResponse);
|
||||
rpc ValidateQuote(ValidateQuoteRequest) returns (ValidateQuoteResponse);
|
||||
rpc ConsumeQuote(ConsumeQuoteRequest) returns (ConsumeQuoteResponse);
|
||||
rpc LatestRate(LatestRateRequest) returns (LatestRateResponse);
|
||||
rpc ListPairs(ListPairsRequest) returns (ListPairsResponse);
|
||||
}
|
||||
8
api/proto/password_reset.proto
Normal file
8
api/proto/password_reset.proto
Normal file
@@ -0,0 +1,8 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/generated/gmessaging";
|
||||
|
||||
message PasswordResetEvent {
|
||||
string AccountRef = 1;
|
||||
string ResetToken = 2;
|
||||
}
|
||||
222
api/proto/payments/orchestrator/v1/orchestrator.proto
Normal file
222
api/proto/payments/orchestrator/v1/orchestrator.proto
Normal file
@@ -0,0 +1,222 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package payments.orchestrator.v1;
|
||||
|
||||
option go_package = "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1;orchestratorv1";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "common/money/v1/money.proto";
|
||||
import "common/fx/v1/fx.proto";
|
||||
import "common/trace/v1/trace.proto";
|
||||
import "common/pagination/v1/cursor.proto";
|
||||
import "billing/fees/v1/fees.proto";
|
||||
import "chain/gateway/v1/gateway.proto";
|
||||
import "oracle/v1/oracle.proto";
|
||||
|
||||
enum PaymentKind {
|
||||
PAYMENT_KIND_UNSPECIFIED = 0;
|
||||
PAYMENT_KIND_PAYOUT = 1;
|
||||
PAYMENT_KIND_INTERNAL_TRANSFER = 2;
|
||||
PAYMENT_KIND_FX_CONVERSION = 3;
|
||||
}
|
||||
|
||||
enum PaymentState {
|
||||
PAYMENT_STATE_UNSPECIFIED = 0;
|
||||
PAYMENT_STATE_ACCEPTED = 1;
|
||||
PAYMENT_STATE_FUNDS_RESERVED = 2;
|
||||
PAYMENT_STATE_SUBMITTED = 3;
|
||||
PAYMENT_STATE_SETTLED = 4;
|
||||
PAYMENT_STATE_FAILED = 5;
|
||||
PAYMENT_STATE_CANCELLED = 6;
|
||||
}
|
||||
|
||||
enum PaymentFailureCode {
|
||||
PAYMENT_FAILURE_CODE_UNSPECIFIED = 0;
|
||||
PAYMENT_FAILURE_CODE_BALANCE = 1;
|
||||
PAYMENT_FAILURE_CODE_LEDGER = 2;
|
||||
PAYMENT_FAILURE_CODE_FX = 3;
|
||||
PAYMENT_FAILURE_CODE_CHAIN = 4;
|
||||
PAYMENT_FAILURE_CODE_FEES = 5;
|
||||
PAYMENT_FAILURE_CODE_POLICY = 6;
|
||||
}
|
||||
|
||||
message RequestMeta {
|
||||
string organization_ref = 1;
|
||||
common.trace.v1.TraceContext trace = 2;
|
||||
}
|
||||
|
||||
message LedgerEndpoint {
|
||||
string ledger_account_ref = 1;
|
||||
string contra_ledger_account_ref = 2;
|
||||
}
|
||||
|
||||
message ManagedWalletEndpoint {
|
||||
string managed_wallet_ref = 1;
|
||||
chain.gateway.v1.Asset asset = 2;
|
||||
}
|
||||
|
||||
message ExternalChainEndpoint {
|
||||
chain.gateway.v1.Asset asset = 1;
|
||||
string address = 2;
|
||||
string memo = 3;
|
||||
}
|
||||
|
||||
message PaymentEndpoint {
|
||||
oneof endpoint {
|
||||
LedgerEndpoint ledger = 1;
|
||||
ManagedWalletEndpoint managed_wallet = 2;
|
||||
ExternalChainEndpoint external_chain = 3;
|
||||
}
|
||||
map<string, string> metadata = 10;
|
||||
}
|
||||
|
||||
message FXIntent {
|
||||
common.fx.v1.CurrencyPair pair = 1;
|
||||
common.fx.v1.Side side = 2;
|
||||
bool firm = 3;
|
||||
int64 ttl_ms = 4;
|
||||
string preferred_provider = 5;
|
||||
int32 max_age_ms = 6;
|
||||
}
|
||||
|
||||
message PaymentIntent {
|
||||
PaymentKind kind = 1;
|
||||
PaymentEndpoint source = 2;
|
||||
PaymentEndpoint destination = 3;
|
||||
common.money.v1.Money amount = 4;
|
||||
bool requires_fx = 5;
|
||||
FXIntent fx = 6;
|
||||
fees.v1.PolicyOverrides fee_policy = 7;
|
||||
map<string, string> attributes = 8;
|
||||
}
|
||||
|
||||
message PaymentQuote {
|
||||
common.money.v1.Money debit_amount = 1;
|
||||
common.money.v1.Money expected_settlement_amount = 2;
|
||||
common.money.v1.Money expected_fee_total = 3;
|
||||
repeated fees.v1.DerivedPostingLine fee_lines = 4;
|
||||
repeated fees.v1.AppliedRule fee_rules = 5;
|
||||
oracle.v1.Quote fx_quote = 6;
|
||||
chain.gateway.v1.EstimateTransferFeeResponse network_fee = 7;
|
||||
string fee_quote_token = 8;
|
||||
}
|
||||
|
||||
message ExecutionRefs {
|
||||
string debit_entry_ref = 1;
|
||||
string credit_entry_ref = 2;
|
||||
string fx_entry_ref = 3;
|
||||
string chain_transfer_ref = 4;
|
||||
}
|
||||
|
||||
message Payment {
|
||||
string payment_ref = 1;
|
||||
string idempotency_key = 2;
|
||||
PaymentIntent intent = 3;
|
||||
PaymentState state = 4;
|
||||
PaymentFailureCode failure_code = 5;
|
||||
string failure_reason = 6;
|
||||
PaymentQuote last_quote = 7;
|
||||
ExecutionRefs execution = 8;
|
||||
map<string, string> metadata = 9;
|
||||
google.protobuf.Timestamp created_at = 10;
|
||||
google.protobuf.Timestamp updated_at = 11;
|
||||
}
|
||||
|
||||
message QuotePaymentRequest {
|
||||
RequestMeta meta = 1;
|
||||
string idempotency_key = 2;
|
||||
PaymentIntent intent = 3;
|
||||
bool preview_only = 4;
|
||||
}
|
||||
|
||||
message QuotePaymentResponse {
|
||||
PaymentQuote quote = 1;
|
||||
}
|
||||
|
||||
message InitiatePaymentRequest {
|
||||
RequestMeta meta = 1;
|
||||
string idempotency_key = 2;
|
||||
PaymentIntent intent = 3;
|
||||
string fee_quote_token = 4;
|
||||
string fx_quote_ref = 5;
|
||||
map<string, string> metadata = 6;
|
||||
}
|
||||
|
||||
message InitiatePaymentResponse {
|
||||
Payment payment = 1;
|
||||
}
|
||||
|
||||
message GetPaymentRequest {
|
||||
RequestMeta meta = 1;
|
||||
string payment_ref = 2;
|
||||
}
|
||||
|
||||
message GetPaymentResponse {
|
||||
Payment payment = 1;
|
||||
}
|
||||
|
||||
message ListPaymentsRequest {
|
||||
RequestMeta meta = 1;
|
||||
repeated PaymentState filter_states = 2;
|
||||
string source_ref = 3;
|
||||
string destination_ref = 4;
|
||||
common.pagination.v1.CursorPageRequest page = 5;
|
||||
}
|
||||
|
||||
message ListPaymentsResponse {
|
||||
repeated Payment payments = 1;
|
||||
common.pagination.v1.CursorPageResponse page = 2;
|
||||
}
|
||||
|
||||
message CancelPaymentRequest {
|
||||
RequestMeta meta = 1;
|
||||
string payment_ref = 2;
|
||||
string reason = 3;
|
||||
}
|
||||
|
||||
message CancelPaymentResponse {
|
||||
Payment payment = 1;
|
||||
}
|
||||
|
||||
message ProcessTransferUpdateRequest {
|
||||
RequestMeta meta = 1;
|
||||
chain.gateway.v1.TransferStatusChangedEvent event = 2;
|
||||
}
|
||||
|
||||
message ProcessTransferUpdateResponse {
|
||||
Payment payment = 1;
|
||||
}
|
||||
|
||||
message ProcessDepositObservedRequest {
|
||||
RequestMeta meta = 1;
|
||||
chain.gateway.v1.WalletDepositObservedEvent event = 2;
|
||||
}
|
||||
|
||||
message ProcessDepositObservedResponse {
|
||||
Payment payment = 1;
|
||||
}
|
||||
|
||||
message InitiateConversionRequest {
|
||||
RequestMeta meta = 1;
|
||||
string idempotency_key = 2;
|
||||
PaymentEndpoint source = 3;
|
||||
PaymentEndpoint destination = 4;
|
||||
FXIntent fx = 5;
|
||||
fees.v1.PolicyOverrides fee_policy = 6;
|
||||
map<string, string> metadata = 7;
|
||||
}
|
||||
|
||||
message InitiateConversionResponse {
|
||||
Payment conversion = 1;
|
||||
}
|
||||
|
||||
service PaymentOrchestrator {
|
||||
rpc QuotePayment(QuotePaymentRequest) returns (QuotePaymentResponse);
|
||||
rpc InitiatePayment(InitiatePaymentRequest) returns (InitiatePaymentResponse);
|
||||
rpc CancelPayment(CancelPaymentRequest) returns (CancelPaymentResponse);
|
||||
rpc GetPayment(GetPaymentRequest) returns (GetPaymentResponse);
|
||||
rpc ListPayments(ListPaymentsRequest) returns (ListPaymentsResponse);
|
||||
rpc InitiateConversion(InitiateConversionRequest) returns (InitiateConversionResponse);
|
||||
rpc ProcessTransferUpdate(ProcessTransferUpdateRequest) returns (ProcessTransferUpdateResponse);
|
||||
rpc ProcessDepositObserved(ProcessDepositObservedRequest) returns (ProcessDepositObservedResponse);
|
||||
}
|
||||
Reference in New Issue
Block a user