feat: add asset operation wallet ledger
Some checks failed
CI / verify (pull_request) Has been cancelled

This commit is contained in:
2026-04-28 12:14:07 +08:00
parent 3cdbf36859
commit 04dfce57e6
16 changed files with 780 additions and 669 deletions

View File

@@ -1,3 +1,5 @@
use std::future::Future;
use axum::http::StatusCode;
use serde_json::json;
use spacetime_client::SpacetimeClientError;
@@ -6,15 +8,36 @@ use crate::{http_error::AppError, state::AppState};
pub(crate) const ASSET_OPERATION_POINTS_COST: u64 = 1;
/// 资产操作统一执行入口:业务层只声明操作类型与资源 ID钱包扣退费由服务层收口。
pub(crate) async fn execute_billable_asset_operation<T, Fut>(
state: &AppState,
owner_user_id: &str,
asset_kind: &str,
asset_id: &str,
operation: Fut,
) -> Result<T, AppError>
where
Fut: Future<Output = Result<T, AppError>>,
{
consume_asset_operation_points(state, owner_user_id, asset_kind, asset_id).await?;
match operation.await {
Ok(value) => Ok(value),
Err(error) => {
refund_asset_operation_points(state, owner_user_id, asset_kind, asset_id).await;
Err(error)
}
}
}
/// 资产操作统一预扣叙世币;扣费流水 ID 由业务资源 ID 参与构造,保证重试幂等。
pub(crate) async fn consume_asset_operation_points(
async fn consume_asset_operation_points(
state: &AppState,
owner_user_id: &str,
asset_kind: &str,
asset_id: &str,
) -> Result<(), AppError> {
let ledger_id = format!(
"asset_generation_consume:{}:{}:{}",
"asset_operation_consume:{}:{}:{}",
owner_user_id, asset_kind, asset_id
);
state
@@ -31,14 +54,14 @@ pub(crate) async fn consume_asset_operation_points(
}
/// 外部生成或发布 mutation 失败后补偿退款;退款失败只记日志,避免覆盖原始业务错误。
pub(crate) async fn refund_asset_operation_points(
async fn refund_asset_operation_points(
state: &AppState,
owner_user_id: &str,
asset_kind: &str,
asset_id: &str,
) {
let ledger_id = format!(
"asset_generation_refund:{}:{}:{}",
"asset_operation_refund:{}:{}:{}",
owner_user_id, asset_kind, asset_id
);
if let Err(error) = state