gcx/blockchain/explorer/issuer-profile.ex

101 lines
3.3 KiB
Elixir

defmodule BlockScoutWeb.IssuerProfile do
@moduledoc """
Blockscout 定制模块:发行方档案页 (P0)
聚合某发行方的所有券批次、保障资金、信用评级
"""
alias Explorer.SmartContract.Reader
@treasury_abi [
%{
"name" => "getGuaranteeBalance",
"type" => "function",
"stateMutability" => "view",
"inputs" => [%{"name" => "issuer", "type" => "address"}],
"outputs" => [%{"name" => "", "type" => "uint256"}]
}
]
@coupon_factory_abi [
%{
"name" => "getIssuerBatches",
"type" => "function",
"stateMutability" => "view",
"inputs" => [%{"name" => "issuer", "type" => "address"}],
"outputs" => [%{"name" => "", "type" => "uint256[]"}]
}
]
@doc "获取发行方完整档案"
def get_issuer_profile(issuer_address, contracts) do
%{
address: issuer_address,
batches: get_issuer_batches(issuer_address, contracts.coupon_factory),
guarantee_fund: get_guarantee_balance(issuer_address, contracts.treasury),
total_coupons_issued: count_total_issued(issuer_address, contracts.coupon_factory),
active_coupons: count_active_coupons(issuer_address, contracts.coupon_factory),
compliance_status: get_compliance_status(issuer_address, contracts.compliance),
credit_rating: calculate_credit_rating(issuer_address, contracts)
}
end
@doc "获取发行方的所有券批次"
def get_issuer_batches(issuer_address, factory_contract) do
case Reader.query_contract(factory_contract, @coupon_factory_abi, %{
"getIssuerBatches" => [issuer_address]
}) do
%{"getIssuerBatches" => {:ok, [batch_ids]}} ->
Enum.map(batch_ids, fn batch_id ->
%{
batch_id: batch_id,
details: BlockScoutWeb.CouponView.get_batch_summary(batch_id, factory_contract)
}
end)
_ ->
[]
end
end
@doc "获取保障资金余额"
def get_guarantee_balance(issuer_address, treasury_contract) do
case Reader.query_contract(treasury_contract, @treasury_abi, %{
"getGuaranteeBalance" => [issuer_address]
}) do
%{"getGuaranteeBalance" => {:ok, [balance]}} ->
%{raw: balance, formatted: format_stable_amount(balance)}
_ ->
%{raw: 0, formatted: "0.00"}
end
end
@doc "计算发行方信用评级 (A-D)"
def calculate_credit_rating(issuer_address, contracts) do
guarantee = get_guarantee_balance(issuer_address, contracts.treasury)
total_issued = count_total_issued(issuer_address, contracts.coupon_factory)
redemption_rate = get_redemption_rate(issuer_address, contracts)
cond do
guarantee.raw > total_issued * 0.5 and redemption_rate > 0.95 -> "A"
guarantee.raw > total_issued * 0.3 and redemption_rate > 0.85 -> "B"
guarantee.raw > total_issued * 0.1 and redemption_rate > 0.70 -> "C"
true -> "D"
end
end
# ── 私有函数 ──
defp count_total_issued(_issuer, _factory), do: 0
defp count_active_coupons(_issuer, _factory), do: 0
defp get_compliance_status(_issuer, _compliance), do: :compliant
defp get_redemption_rate(_issuer, _contracts), do: 1.0
defp format_stable_amount(amount) when is_integer(amount) do
# 稳定币 6 位精度
:erlang.float_to_binary(amount / 1_000_000, decimals: 2)
end
defp format_stable_amount(_), do: "0.00"
end