Files
smom-dbis-138/chaincode/reserve-manager/go/reserve_manager.go
defiQUG 6dcadc86a2 chore(omnl): consolidate portal and domain routing updates
Capture non-secret OMNL portal, journal, chain, and nginx routing updates from the operator cleanup session while leaving generated auth includes unstaged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 09:57:01 -07:00

313 lines
9.3 KiB
Go

package main
import (
"encoding/json"
"fmt"
"strconv"
"time"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
// ReserveManagerContract provides functions for managing reserves
type ReserveManagerContract struct {
contractapi.Contract
}
// Reserve represents a reserve backing tokenized assets
type Reserve struct {
ReserveID string `json:"reserveId"`
AssetType string `json:"assetType"` // EUR, USD, etc.
TotalAmount string `json:"totalAmount"`
BackedAmount string `json:"backedAmount"` // Amount already backing tokens
AvailableAmount string `json:"availableAmount"` // Available for new tokens
Attestor string `json:"attestor"`
AttestationHash string `json:"attestationHash"`
LastVerified string `json:"lastVerified"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
// AttestationRequest represents a request to attest to reserves
type AttestationRequest struct {
ReserveID string `json:"reserveId"`
AssetType string `json:"assetType"`
TotalAmount string `json:"totalAmount"`
Attestor string `json:"attestor"`
AttestationHash string `json:"attestationHash"`
Proof string `json:"proof"`
}
// VerifyReserve verifies that reserves are sufficient for tokenization
func (s *ReserveManagerContract) VerifyReserve(ctx contractapi.TransactionContextInterface, reserveID string, amount string) (bool, error) {
reserveJSON, err := ctx.GetStub().GetState(reserveID)
if err != nil {
return false, fmt.Errorf("failed to read reserve from world state: %v", err)
}
if reserveJSON == nil {
return false, fmt.Errorf("reserve %s does not exist", reserveID)
}
var reserve Reserve
err = json.Unmarshal(reserveJSON, &reserve)
if err != nil {
return false, err
}
// Parse amounts
requestAmount, err := strconv.ParseFloat(amount, 64)
if err != nil {
return false, fmt.Errorf("invalid amount: %v", err)
}
availableAmount, err := strconv.ParseFloat(reserve.AvailableAmount, 64)
if err != nil {
return false, fmt.Errorf("invalid available amount: %v", err)
}
// Check if sufficient reserve available
if requestAmount > availableAmount {
return false, fmt.Errorf("insufficient reserve: requested %f, available %f", requestAmount, availableAmount)
}
// Verify attestation is recent (within 24 hours)
lastVerified, err := time.Parse(time.RFC3339, reserve.LastVerified)
if err != nil {
return false, fmt.Errorf("invalid last verified timestamp: %v", err)
}
if time.Since(lastVerified) > 24*time.Hour {
return false, fmt.Errorf("reserve attestation is stale (older than 24 hours)")
}
return true, nil
}
// CreateReserve creates a new reserve with attestation
func (s *ReserveManagerContract) CreateReserve(ctx contractapi.TransactionContextInterface, requestJSON string) error {
var request AttestationRequest
err := json.Unmarshal([]byte(requestJSON), &request)
if err != nil {
return fmt.Errorf("failed to unmarshal attestation request: %v", err)
}
// Check if reserve already exists
existing, err := ctx.GetStub().GetState(request.ReserveID)
if err != nil {
return fmt.Errorf("failed to read from world state: %v", err)
}
if existing != nil {
return fmt.Errorf("reserve %s already exists", request.ReserveID)
}
// Validate total amount parses as a number
if _, err := strconv.ParseFloat(request.TotalAmount, 64); err != nil {
return fmt.Errorf("invalid total amount: %v", err)
}
// Create reserve
reserve := Reserve{
ReserveID: request.ReserveID,
AssetType: request.AssetType,
TotalAmount: request.TotalAmount,
BackedAmount: "0.00",
AvailableAmount: request.TotalAmount,
Attestor: request.Attestor,
AttestationHash: request.AttestationHash,
LastVerified: time.Now().Format(time.RFC3339),
CreatedAt: time.Now().Format(time.RFC3339),
UpdatedAt: time.Now().Format(time.RFC3339),
}
reserveJSON, err := json.Marshal(reserve)
if err != nil {
return err
}
err = ctx.GetStub().PutState(request.ReserveID, reserveJSON)
if err != nil {
return fmt.Errorf("failed to put reserve to world state: %v", err)
}
// Emit event
eventPayload := fmt.Sprintf(`{"reserveId":"%s","action":"create","amount":"%s","attestor":"%s"}`,
request.ReserveID, request.TotalAmount, request.Attestor)
err = ctx.GetStub().SetEvent("ReserveCreated", []byte(eventPayload))
if err != nil {
return fmt.Errorf("failed to emit event: %v", err)
}
return nil
}
// AttestReserve updates reserve attestation
func (s *ReserveManagerContract) AttestReserve(ctx contractapi.TransactionContextInterface, requestJSON string) error {
var request AttestationRequest
err := json.Unmarshal([]byte(requestJSON), &request)
if err != nil {
return fmt.Errorf("failed to unmarshal attestation request: %v", err)
}
// Get existing reserve
reserveJSON, err := ctx.GetStub().GetState(request.ReserveID)
if err != nil {
return fmt.Errorf("failed to read reserve from world state: %v", err)
}
if reserveJSON == nil {
return fmt.Errorf("reserve %s does not exist", request.ReserveID)
}
var reserve Reserve
err = json.Unmarshal(reserveJSON, &reserve)
if err != nil {
return err
}
// Update attestation
reserve.Attestor = request.Attestor
reserve.AttestationHash = request.AttestationHash
reserve.TotalAmount = request.TotalAmount
// Recalculate available amount
totalAmount, err := strconv.ParseFloat(request.TotalAmount, 64)
if err != nil {
return fmt.Errorf("invalid total amount: %v", err)
}
backedAmount, err := strconv.ParseFloat(reserve.BackedAmount, 64)
if err != nil {
return fmt.Errorf("invalid backed amount: %v", err)
}
availableAmount := totalAmount - backedAmount
reserve.AvailableAmount = fmt.Sprintf("%.2f", availableAmount)
reserve.LastVerified = time.Now().Format(time.RFC3339)
reserve.UpdatedAt = time.Now().Format(time.RFC3339)
updatedJSON, err := json.Marshal(reserve)
if err != nil {
return err
}
err = ctx.GetStub().PutState(request.ReserveID, updatedJSON)
if err != nil {
return fmt.Errorf("failed to update reserve in world state: %v", err)
}
// Emit event
eventPayload := fmt.Sprintf(`{"reserveId":"%s","action":"attest","amount":"%s","attestor":"%s"}`,
request.ReserveID, request.TotalAmount, request.Attestor)
err = ctx.GetStub().SetEvent("ReserveAttested", []byte(eventPayload))
if err != nil {
return fmt.Errorf("failed to emit event: %v", err)
}
return nil
}
// AllocateReserve allocates reserve amount for token backing
func (s *ReserveManagerContract) AllocateReserve(ctx contractapi.TransactionContextInterface, reserveID string, amount string) error {
reserveJSON, err := ctx.GetStub().GetState(reserveID)
if err != nil {
return fmt.Errorf("failed to read reserve from world state: %v", err)
}
if reserveJSON == nil {
return fmt.Errorf("reserve %s does not exist", reserveID)
}
var reserve Reserve
err = json.Unmarshal(reserveJSON, &reserve)
if err != nil {
return err
}
// Parse amounts
allocateAmount, err := strconv.ParseFloat(amount, 64)
if err != nil {
return fmt.Errorf("invalid amount: %v", err)
}
availableAmount, err := strconv.ParseFloat(reserve.AvailableAmount, 64)
if err != nil {
return fmt.Errorf("invalid available amount: %v", err)
}
if allocateAmount > availableAmount {
return fmt.Errorf("insufficient available reserve: requested %f, available %f", allocateAmount, availableAmount)
}
// Update reserve
backedAmount, err := strconv.ParseFloat(reserve.BackedAmount, 64)
if err != nil {
return fmt.Errorf("invalid backed amount: %v", err)
}
reserve.BackedAmount = fmt.Sprintf("%.2f", backedAmount+allocateAmount)
reserve.AvailableAmount = fmt.Sprintf("%.2f", availableAmount-allocateAmount)
reserve.UpdatedAt = time.Now().Format(time.RFC3339)
updatedJSON, err := json.Marshal(reserve)
if err != nil {
return err
}
err = ctx.GetStub().PutState(reserveID, updatedJSON)
if err != nil {
return fmt.Errorf("failed to update reserve in world state: %v", err)
}
return nil
}
// GetReserve returns reserve details
func (s *ReserveManagerContract) GetReserve(ctx contractapi.TransactionContextInterface, reserveID string) (*Reserve, error) {
reserveJSON, err := ctx.GetStub().GetState(reserveID)
if err != nil {
return nil, fmt.Errorf("failed to read from world state: %v", err)
}
if reserveJSON == nil {
return nil, fmt.Errorf("reserve %s does not exist", reserveID)
}
var reserve Reserve
err = json.Unmarshal(reserveJSON, &reserve)
if err != nil {
return nil, err
}
return &reserve, nil
}
// Enforce1To1Backing verifies 1:1 backing ratio
func (s *ReserveManagerContract) Enforce1To1Backing(ctx contractapi.TransactionContextInterface, reserveID string) (bool, error) {
reserve, err := s.GetReserve(ctx, reserveID)
if err != nil {
return false, err
}
totalAmount, err := strconv.ParseFloat(reserve.TotalAmount, 64)
if err != nil {
return false, err
}
backedAmount, err := strconv.ParseFloat(reserve.BackedAmount, 64)
if err != nil {
return false, err
}
// Check if total reserve >= backed amount (1:1 ratio)
return totalAmount >= backedAmount, nil
}
func main() {
chaincode, err := contractapi.NewChaincode(&ReserveManagerContract{})
if err != nil {
fmt.Printf("Error creating reserve manager chaincode: %v", err)
return
}
if err := chaincode.Start(); err != nil {
fmt.Printf("Error starting reserve manager chaincode: %v", err)
}
}