140 lines
5.2 KiB
Go
140 lines
5.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"math/big"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Config struct {
|
|
ListenAddr string
|
|
DBPath string
|
|
AllowedOrigin string
|
|
MemberPollIntervalSec int
|
|
IntentTTL time.Duration
|
|
QuoteTTL time.Duration
|
|
WalletSessionTTL time.Duration
|
|
RequireWalletSession bool
|
|
InstallTokenTTL time.Duration
|
|
LeaseTTL time.Duration
|
|
OfflineRenewTTL time.Duration
|
|
ChainID int64
|
|
DomainName string
|
|
VerifyingContract string
|
|
MembershipContract string
|
|
EntitlementContract string
|
|
MintCurrency string
|
|
MintAmountAtomic string
|
|
MintDecimals int
|
|
ChainRPCURL string
|
|
RequireOnchainTxVerify bool
|
|
GovernanceRuntimeVersion string
|
|
GovernancePackageURL string
|
|
GovernancePackageHash string
|
|
GovernancePackageSig string
|
|
GovernanceSignerKeyID string
|
|
GovernancePolicyHash string
|
|
GovernanceRolloutChannel string
|
|
}
|
|
|
|
func loadConfig() Config {
|
|
return Config{
|
|
ListenAddr: env("SECRET_API_LISTEN_ADDR", ":8080"),
|
|
DBPath: env("SECRET_API_DB_PATH", "./secret.db"),
|
|
AllowedOrigin: env("SECRET_API_ALLOWED_ORIGIN", "https://edut.ai"),
|
|
MemberPollIntervalSec: envInt("SECRET_API_MEMBER_POLL_INTERVAL_SECONDS", 30),
|
|
IntentTTL: time.Duration(envInt("SECRET_API_INTENT_TTL_SECONDS", 900)) * time.Second,
|
|
QuoteTTL: time.Duration(envInt("SECRET_API_QUOTE_TTL_SECONDS", 900)) * time.Second,
|
|
WalletSessionTTL: time.Duration(envInt("SECRET_API_WALLET_SESSION_TTL_SECONDS", 2592000)) * time.Second,
|
|
RequireWalletSession: envBool("SECRET_API_REQUIRE_WALLET_SESSION", false),
|
|
InstallTokenTTL: time.Duration(envInt("SECRET_API_INSTALL_TOKEN_TTL_SECONDS", 900)) * time.Second,
|
|
LeaseTTL: time.Duration(envInt("SECRET_API_LEASE_TTL_SECONDS", 3600)) * time.Second,
|
|
OfflineRenewTTL: time.Duration(envInt("SECRET_API_OFFLINE_RENEW_TTL_SECONDS", 2592000)) * time.Second,
|
|
ChainID: int64(envInt("SECRET_API_CHAIN_ID", 84532)),
|
|
DomainName: env("SECRET_API_DOMAIN_NAME", "EDUT Designation"),
|
|
VerifyingContract: strings.ToLower(env("SECRET_API_VERIFYING_CONTRACT", "0x0000000000000000000000000000000000000000")),
|
|
MembershipContract: strings.ToLower(env("SECRET_API_MEMBERSHIP_CONTRACT", "0x0000000000000000000000000000000000000000")),
|
|
EntitlementContract: strings.ToLower(env("SECRET_API_ENTITLEMENT_CONTRACT", "0x0000000000000000000000000000000000000000")),
|
|
MintCurrency: strings.ToUpper(env("SECRET_API_MINT_CURRENCY", "USDC")),
|
|
MintAmountAtomic: env("SECRET_API_MINT_AMOUNT_ATOMIC", "100000000"),
|
|
MintDecimals: envInt("SECRET_API_MINT_DECIMALS", 6),
|
|
ChainRPCURL: env("SECRET_API_CHAIN_RPC_URL", ""),
|
|
RequireOnchainTxVerify: envBool("SECRET_API_REQUIRE_ONCHAIN_TX_VERIFICATION", false),
|
|
GovernanceRuntimeVersion: env("SECRET_API_GOV_RUNTIME_VERSION", "0.1.0"),
|
|
GovernancePackageURL: env("SECRET_API_GOV_PACKAGE_URL", "https://cdn.edut.ai/governance/edutd-0.1.0.tar.gz"),
|
|
GovernancePackageHash: strings.ToLower(env("SECRET_API_GOV_PACKAGE_HASH", "sha256:pending")),
|
|
GovernancePackageSig: env("SECRET_API_GOV_PACKAGE_SIGNATURE", "pending"),
|
|
GovernanceSignerKeyID: env("SECRET_API_GOV_SIGNER_KEY_ID", "edut-signer-1"),
|
|
GovernancePolicyHash: strings.ToLower(env("SECRET_API_GOV_POLICY_HASH", "sha256:pending")),
|
|
GovernanceRolloutChannel: strings.ToLower(env("SECRET_API_GOV_ROLLOUT_CHANNEL", "stable")),
|
|
}
|
|
}
|
|
|
|
func (c Config) Validate() error {
|
|
if c.ChainID <= 0 {
|
|
return fmt.Errorf("SECRET_API_CHAIN_ID must be positive")
|
|
}
|
|
currency := strings.ToUpper(strings.TrimSpace(c.MintCurrency))
|
|
switch currency {
|
|
case "USDC":
|
|
if c.MintDecimals != 6 {
|
|
return fmt.Errorf("SECRET_API_MINT_DECIMALS must be 6 for USDC")
|
|
}
|
|
case "ETH":
|
|
if c.MintDecimals != 18 {
|
|
return fmt.Errorf("SECRET_API_MINT_DECIMALS must be 18 for ETH")
|
|
}
|
|
default:
|
|
return fmt.Errorf("SECRET_API_MINT_CURRENCY must be USDC or ETH")
|
|
}
|
|
amountRaw := strings.TrimSpace(c.MintAmountAtomic)
|
|
amount, ok := new(big.Int).SetString(amountRaw, 10)
|
|
if !ok || amount.Sign() <= 0 {
|
|
return fmt.Errorf("SECRET_API_MINT_AMOUNT_ATOMIC must be a positive base-10 integer")
|
|
}
|
|
if c.WalletSessionTTL <= 0 {
|
|
return fmt.Errorf("SECRET_API_WALLET_SESSION_TTL_SECONDS must be positive")
|
|
}
|
|
if c.RequireOnchainTxVerify && strings.TrimSpace(c.ChainRPCURL) == "" {
|
|
return fmt.Errorf("SECRET_API_REQUIRE_ONCHAIN_TX_VERIFICATION requires SECRET_API_CHAIN_RPC_URL")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func env(key, fallback string) string {
|
|
if v := strings.TrimSpace(os.Getenv(key)); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func envInt(key string, fallback int) int {
|
|
raw := strings.TrimSpace(os.Getenv(key))
|
|
if raw == "" {
|
|
return fallback
|
|
}
|
|
value, err := strconv.Atoi(raw)
|
|
if err != nil {
|
|
return fallback
|
|
}
|
|
return value
|
|
}
|
|
|
|
func envBool(key string, fallback bool) bool {
|
|
raw := strings.ToLower(strings.TrimSpace(os.Getenv(key)))
|
|
if raw == "" {
|
|
return fallback
|
|
}
|
|
switch raw {
|
|
case "1", "true", "yes", "on":
|
|
return true
|
|
case "0", "false", "no", "off":
|
|
return false
|
|
default:
|
|
return fallback
|
|
}
|
|
}
|