101 lines
3.3 KiB
Elixir
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
|