42 lines
1.1 KiB
Go
42 lines
1.1 KiB
Go
package kernel
|
|
|
|
import (
|
|
"errors"
|
|
"math/big"
|
|
)
|
|
|
|
var (
|
|
ErrInvalidTokenBilling = errors.New("invalid token billing parameters")
|
|
ErrTokenBillingOverflow = errors.New("token billing amount overflows int64")
|
|
)
|
|
|
|
type TokenBillingTerm struct {
|
|
Tokens int64
|
|
PriceMicrocredits int64
|
|
}
|
|
|
|
// TokenBillingAmount 按每百万 Token 单价及万分比倍率汇总费用,只对最终微积分金额上取整。
|
|
func TokenBillingAmount(multiplierBPS int64, terms ...TokenBillingTerm) (int64, error) {
|
|
if multiplierBPS <= 0 {
|
|
return 0, ErrInvalidTokenBilling
|
|
}
|
|
var total, product big.Int
|
|
for _, term := range terms {
|
|
if term.Tokens < 0 || term.PriceMicrocredits < 0 {
|
|
return 0, ErrInvalidTokenBilling
|
|
}
|
|
product.Mul(big.NewInt(term.Tokens), big.NewInt(term.PriceMicrocredits))
|
|
total.Add(&total, &product)
|
|
}
|
|
total.Mul(&total, big.NewInt(multiplierBPS))
|
|
var remainder big.Int
|
|
total.QuoRem(&total, big.NewInt(10_000_000_000), &remainder)
|
|
if remainder.Sign() != 0 {
|
|
total.Add(&total, big.NewInt(1))
|
|
}
|
|
if !total.IsInt64() {
|
|
return 0, ErrTokenBillingOverflow
|
|
}
|
|
return total.Int64(), nil
|
|
}
|