From 3b71da20b9948208ce9ef4c8c3bb3817db3ad605 Mon Sep 17 00:00:00 2001 From: SIDANWhatever Date: Fri, 20 Dec 2024 16:32:42 +0800 Subject: [PATCH] feat: refactor folder structure --- models/asset.go => asset.go | 2 +- providers/blockfrost.go => blockfrost.go | 38 ++++--- interfaces.go | 31 ++++++ interfaces/provider.go | 33 ------ providers/maestro.go => maestro.go | 40 ++++--- main.go | 7 -- models.go | 123 ++++++++++++++++++++++ models/account_info.go | 9 -- models/asset_metadata.go | 3 - models/block_info.go | 19 ---- models/network.go | 25 ----- models/protocol.go | 25 ----- models/transaction_info.go | 13 --- models/utxo.go | 35 ------- models/value.go | 108 ------------------- {models => tests}/asset_test.go | 41 +++----- {providers => tests}/blockfrost_test.go | 13 ++- {providers => tests}/maestro_test.go | 15 ++- {models => tests}/value_test.go | 85 +++++++-------- utils.go | 10 ++ utils/utils.go | 12 --- value.go | 126 +++++++++++++++++++++++ 22 files changed, 391 insertions(+), 422 deletions(-) rename models/asset.go => asset.go (98%) rename providers/blockfrost.go => blockfrost.go (80%) create mode 100644 interfaces.go delete mode 100644 interfaces/provider.go rename providers/maestro.go => maestro.go (72%) delete mode 100644 main.go create mode 100644 models.go delete mode 100644 models/account_info.go delete mode 100644 models/asset_metadata.go delete mode 100644 models/block_info.go delete mode 100644 models/network.go delete mode 100644 models/protocol.go delete mode 100644 models/transaction_info.go delete mode 100644 models/utxo.go delete mode 100644 models/value.go rename {models => tests}/asset_test.go (69%) rename {providers => tests}/blockfrost_test.go (67%) rename {providers => tests}/maestro_test.go (72%) rename {models => tests}/value_test.go (74%) create mode 100644 utils.go delete mode 100644 utils/utils.go create mode 100644 value.go diff --git a/models/asset.go b/asset.go similarity index 98% rename from models/asset.go rename to asset.go index 505c4ab..755d62d 100644 --- a/models/asset.go +++ b/asset.go @@ -1,4 +1,4 @@ -package models +package rum import "strconv" diff --git a/providers/blockfrost.go b/blockfrost.go similarity index 80% rename from providers/blockfrost.go rename to blockfrost.go index 62f162d..2841a1e 100644 --- a/providers/blockfrost.go +++ b/blockfrost.go @@ -1,4 +1,4 @@ -package providers +package rum import ( "context" @@ -6,8 +6,6 @@ import ( "strconv" "github.com/blockfrost/blockfrost-go" - "github.com/sidan-lab/rum/models" - "github.com/sidan-lab/rum/utils" ) var NetworkMap = map[string]string{ @@ -53,10 +51,10 @@ func (bf *BlockfrostProvider) SubmitTx(txCbor string) (string, error) { return txHash, err } -func (bf *BlockfrostProvider) FetchTxInfo(hash string) (models.TransactionInfo, error) { +func (bf *BlockfrostProvider) FetchTxInfo(hash string) (TransactionInfo, error) { bfTxInfo, err := bf.blockfrostClient.Transaction(context.TODO(), hash) if err != nil { - return models.TransactionInfo{}, err + return TransactionInfo{}, err } invalidHereafter := "" @@ -68,7 +66,7 @@ func (bf *BlockfrostProvider) FetchTxInfo(hash string) (models.TransactionInfo, invalidBefore = *bfTxInfo.InvalidBefore } - txInfo := models.TransactionInfo{ + txInfo := TransactionInfo{ Block: bfTxInfo.Block, Deposit: bfTxInfo.Deposit, Fees: bfTxInfo.Fees, @@ -82,7 +80,7 @@ func (bf *BlockfrostProvider) FetchTxInfo(hash string) (models.TransactionInfo, return txInfo, nil } -func (bf *BlockfrostProvider) FetchUTxOs(hash string, index *int) ([]models.UTxO, error) { +func (bf *BlockfrostProvider) FetchUTxOs(hash string, index *int) ([]UTxO, error) { res, err := bf.blockfrostClient.TransactionUTXOs(context.TODO(), hash) if err != nil { return nil, err @@ -90,24 +88,24 @@ func (bf *BlockfrostProvider) FetchUTxOs(hash string, index *int) ([]models.UTxO bfOutputs := res.Outputs utxos := BfToUtxos(bfOutputs, hash) if index != nil { - utxo := utils.FindUtxoByIndex(utxos, *index) + utxo := FindUtxoByIndex(utxos, *index) if utxo != nil { - return []models.UTxO{*utxo}, nil + return []UTxO{*utxo}, nil } - return []models.UTxO{}, nil + return []UTxO{}, nil } return utxos, nil } -func BfToUtxos(bfUtxos []blockfrost.TransactionOutput, hash string) []models.UTxO { - utxos := make([]models.UTxO, len(bfUtxos)) +func BfToUtxos(bfUtxos []blockfrost.TransactionOutput, hash string) []UTxO { + utxos := make([]UTxO, len(bfUtxos)) for i, bfUtxo := range bfUtxos { utxos[i] = BfToUtxo(bfUtxo, hash) } return utxos } -func BfToUtxo(bfUtxo blockfrost.TransactionOutput, hash string) models.UTxO { +func BfToUtxo(bfUtxo blockfrost.TransactionOutput, hash string) UTxO { dataHash := "" if bfUtxo.DataHash != nil { dataHash = *bfUtxo.DataHash @@ -121,12 +119,12 @@ func BfToUtxo(bfUtxo blockfrost.TransactionOutput, hash string) models.UTxO { referenceScriptHash = *bfUtxo.ReferenceScriptHash } - return models.UTxO{ - Input: models.Input{ + return UTxO{ + Input: Input{ TxHash: hash, OutputIndex: int(bfUtxo.OutputIndex), }, - Output: models.Output{ + Output: Output{ Amount: BfToAssets(bfUtxo.Amount), Address: bfUtxo.Address, DataHash: dataHash, @@ -137,16 +135,16 @@ func BfToUtxo(bfUtxo blockfrost.TransactionOutput, hash string) models.UTxO { } } -func BfToAssets(bfAssets []blockfrost.TxAmount) []models.Asset { - assets := make([]models.Asset, len(bfAssets)) +func BfToAssets(bfAssets []blockfrost.TxAmount) []Asset { + assets := make([]Asset, len(bfAssets)) for i, bfAsset := range bfAssets { assets[i] = BfToAsset(bfAsset) } return assets } -func BfToAsset(bfAsset blockfrost.TxAmount) models.Asset { - return models.Asset{ +func BfToAsset(bfAsset blockfrost.TxAmount) Asset { + return Asset{ Quantity: bfAsset.Quantity, Unit: bfAsset.Unit, } diff --git a/interfaces.go b/interfaces.go new file mode 100644 index 0000000..479683e --- /dev/null +++ b/interfaces.go @@ -0,0 +1,31 @@ +package rum + +type IProvider interface { + IFetcher + ISubmitter +} + +type IFetcher interface { + // FetchAccountInfo(address string) (AccountInfo, error) + // FetchAddressUTxOs(address string, asset *string) ([]UTxO, error) + // FetchAssetAddresses(asset string) ([]struct { + // Address string + // Quantity string + // }, error) + // FetchAssetMetadata(asset string) (AssetMetadata, error) + // FetchBlockInfo(hash string) (BlockInfo, error) + // FetchCollectionAssets(policyId string, cursor *interface{}) (struct { + // Assets Assets + // Next *interface{} + // }, error) + // FetchHandle(handle string) (map[string]interface{}, error) + // FetchHandleAddress(handle string) (string, error) + // FetchProtocolParameters(epoch int) (Protocol, error) + FetchTxInfo(hash string) (TransactionInfo, error) + FetchUTxOs(hash string, index *int) ([]UTxO, error) + // Get(url string) (interface{}, error) +} + +type ISubmitter interface { + SubmitTx(txCbor string) (string, error) +} diff --git a/interfaces/provider.go b/interfaces/provider.go deleted file mode 100644 index e630a1d..0000000 --- a/interfaces/provider.go +++ /dev/null @@ -1,33 +0,0 @@ -package interfaces - -import "github.com/sidan-lab/rum/models" - -type IProvider interface { - IFetcher - ISubmitter -} - -type IFetcher interface { - // FetchAccountInfo(address string) (models.AccountInfo, error) - // FetchAddressUTxOs(address string, asset *string) ([]models.UTxO, error) - // FetchAssetAddresses(asset string) ([]struct { - // Address string - // Quantity string - // }, error) - // FetchAssetMetadata(asset string) (models.AssetMetadata, error) - // FetchBlockInfo(hash string) (models.BlockInfo, error) - // FetchCollectionAssets(policyId string, cursor *interface{}) (struct { - // Assets models.Assets - // Next *interface{} - // }, error) - // FetchHandle(handle string) (map[string]interface{}, error) - // FetchHandleAddress(handle string) (string, error) - // FetchProtocolParameters(epoch int) (models.Protocol, error) - FetchTxInfo(hash string) (models.TransactionInfo, error) - FetchUTxOs(hash string, index *int) ([]models.UTxO, error) - // Get(url string) (interface{}, error) -} - -type ISubmitter interface { - SubmitTx(txCbor string) (string, error) -} diff --git a/providers/maestro.go b/maestro.go similarity index 72% rename from providers/maestro.go rename to maestro.go index 078b7ea..6766b96 100644 --- a/providers/maestro.go +++ b/maestro.go @@ -1,4 +1,4 @@ -package providers +package rum import ( "encoding/json" @@ -6,15 +6,13 @@ import ( "github.com/maestro-org/go-sdk/client" msModel "github.com/maestro-org/go-sdk/models" - "github.com/sidan-lab/rum/models" - "github.com/sidan-lab/rum/utils" ) type MaestroProvider struct { maestroClient *client.Client } -func NewMaestroProvider(apiKey string, network models.Network) *MaestroProvider { +func NewMaestroProvider(apiKey string, network Network) *MaestroProvider { maestroClient := client.NewClient(apiKey, string(network)) return &MaestroProvider{ maestroClient: maestroClient, @@ -26,13 +24,13 @@ func (ms *MaestroProvider) SubmitTx(txCbor string) (string, error) { return txHash, err } -func (ms *MaestroProvider) FetchTxInfo(hash string) (models.TransactionInfo, error) { +func (ms *MaestroProvider) FetchTxInfo(hash string) (TransactionInfo, error) { tx, err := ms.maestroClient.TransactionDetails(hash) if err != nil { - return models.TransactionInfo{}, err + return TransactionInfo{}, err } msTxInfo := tx.Data - txInfo := models.TransactionInfo{ + txInfo := TransactionInfo{ Index: int(msTxInfo.BlockTxIndex), Block: msTxInfo.BlockHash, Hash: msTxInfo.TxHash, @@ -52,7 +50,7 @@ type MsDatum struct { Json any `json:"json"` } -func (ms *MaestroProvider) FetchUTxOs(hash string, index *int) ([]models.UTxO, error) { +func (ms *MaestroProvider) FetchUTxOs(hash string, index *int) ([]UTxO, error) { res, err := ms.maestroClient.TransactionDetails(hash) if err != nil { return nil, err @@ -60,24 +58,24 @@ func (ms *MaestroProvider) FetchUTxOs(hash string, index *int) ([]models.UTxO, e msOutputs := res.Data.Outputs utxos := MsToUtxos(msOutputs) if index != nil { - utxo := utils.FindUtxoByIndex(utxos, *index) + utxo := FindUtxoByIndex(utxos, *index) if utxo != nil { - return []models.UTxO{*utxo}, nil + return []UTxO{*utxo}, nil } - return []models.UTxO{}, nil + return []UTxO{}, nil } return utxos, nil } -func MsToUtxos(msUtxos []msModel.Utxo) []models.UTxO { - utxos := make([]models.UTxO, len(msUtxos)) +func MsToUtxos(msUtxos []msModel.Utxo) []UTxO { + utxos := make([]UTxO, len(msUtxos)) for i, msUtxo := range msUtxos { utxos[i] = MsToUtxo(msUtxo) } return utxos } -func MsToUtxo(msUtxo msModel.Utxo) models.UTxO { +func MsToUtxo(msUtxo msModel.Utxo) UTxO { var datum MsDatum if msUtxo.Datum != nil { datumBytes, err := json.Marshal(msUtxo.Datum) @@ -86,12 +84,12 @@ func MsToUtxo(msUtxo msModel.Utxo) models.UTxO { json.Unmarshal(datumBytes, &datum) } } - return models.UTxO{ - Input: models.Input{ + return UTxO{ + Input: Input{ TxHash: msUtxo.TxHash, OutputIndex: int(msUtxo.Index), }, - Output: models.Output{ + Output: Output{ Amount: MsToAssets(msUtxo.Assets), Address: msUtxo.Address, DataHash: datum.Hash, @@ -102,16 +100,16 @@ func MsToUtxo(msUtxo msModel.Utxo) models.UTxO { } } -func MsToAssets(msAssets []msModel.Asset) []models.Asset { - assets := make([]models.Asset, len(msAssets)) +func MsToAssets(msAssets []msModel.Asset) []Asset { + assets := make([]Asset, len(msAssets)) for i, msAsset := range msAssets { assets[i] = MsToAsset(msAsset) } return assets } -func MsToAsset(msAsset msModel.Asset) models.Asset { - return models.Asset{ +func MsToAsset(msAsset msModel.Asset) Asset { + return Asset{ Quantity: strconv.FormatInt(msAsset.Amount, 10), Unit: msAsset.Unit, } diff --git a/main.go b/main.go deleted file mode 100644 index a3dd973..0000000 --- a/main.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import "fmt" - -func main() { - fmt.Println("Hello, World!") -} diff --git a/models.go b/models.go new file mode 100644 index 0000000..8091515 --- /dev/null +++ b/models.go @@ -0,0 +1,123 @@ +package rum + +type AccountInfo struct { + Active bool + PoolId *string + Balance string + Rewards string + Withdrawals string +} + +type AssetMetadata = map[string]interface{} + +type BlockInfo struct { + Time int + Hash string + Slot string + Epoch int + EpochSlot string + SlotLeader string + Size int + TxCount int + Output string + Fees string + PreviousBlock string + NextBlock string + Confirmations int + OperationalCertificate string + VRFKey string +} + +type Network string + +const ( + Testnet Network = "testnet" + Preview Network = "preview" + Preprod Network = "preprod" + Mainnet Network = "mainnet" +) + +var AllNetworks = []Network{Testnet, Preview, Preprod, Mainnet} + +func (n Network) String() string { + return string(n) +} + +func IsNetwork(value string) bool { + for _, network := range AllNetworks { + if value == network.String() { + return true + } + } + return false +} + +type Protocol struct { + Epoch int + MinFeeA int + MinFeeB int + MaxBlockSize int + MaxTxSize int + MaxBlockHeaderSize int + KeyDeposit int + PoolDeposit int + Decentralisation float64 + MinPoolCost string + PriceMem float64 + PriceStep float64 + MaxTxExMem string + MaxTxExSteps string + MaxBlockExMem string + MaxBlockExSteps string + MaxValSize int + CollateralPercent int + MaxCollateralInputs int + CoinsPerUtxoSize int + MinFeeRefScriptCostPerByte int +} + +type TransactionInfo struct { + Index int + Block string + Hash string + Slot string + Fees string + Size int + Deposit string + InvalidBefore string + InvalidAfter string +} + +type Input struct { + OutputIndex int `json:"output_index" binding:"required"` + TxHash string `json:"tx_hash" binding:"required"` +} + +type Output struct { + Address string `json:"address" binding:"required"` + Amount []Asset `json:"amount" binding:"required"` + DataHash string `json:"data_hash,omitempty"` + PlutusData string `json:"plutus_data,omitempty"` + ScriptRef string `json:"script_ref,omitempty"` + ScriptHash string `json:"script_hash,omitempty"` +} + +type UTxO struct { + Input Input `json:"input" binding:"required"` + Output Output `json:"output" binding:"required"` +} + +func MakeScriptUtxo(txHash string, outputIndex int, address string, amount []Asset, plutusData string, dataHash string) UTxO { + return UTxO{ + Input: Input{ + OutputIndex: outputIndex, + TxHash: txHash, + }, + Output: Output{ + Address: address, + Amount: amount, + DataHash: dataHash, + PlutusData: plutusData, + }, + } +} diff --git a/models/account_info.go b/models/account_info.go deleted file mode 100644 index f0fad61..0000000 --- a/models/account_info.go +++ /dev/null @@ -1,9 +0,0 @@ -package models - -type AccountInfo struct { - Active bool - PoolId *string - Balance string - Rewards string - Withdrawals string -} diff --git a/models/asset_metadata.go b/models/asset_metadata.go deleted file mode 100644 index 30c039d..0000000 --- a/models/asset_metadata.go +++ /dev/null @@ -1,3 +0,0 @@ -package models - -type AssetMetadata = map[string]interface{} diff --git a/models/block_info.go b/models/block_info.go deleted file mode 100644 index abe3121..0000000 --- a/models/block_info.go +++ /dev/null @@ -1,19 +0,0 @@ -package models - -type BlockInfo struct { - Time int - Hash string - Slot string - Epoch int - EpochSlot string - SlotLeader string - Size int - TxCount int - Output string - Fees string - PreviousBlock string - NextBlock string - Confirmations int - OperationalCertificate string - VRFKey string -} diff --git a/models/network.go b/models/network.go deleted file mode 100644 index 7e71e62..0000000 --- a/models/network.go +++ /dev/null @@ -1,25 +0,0 @@ -package models - -type Network string - -const ( - Testnet Network = "testnet" - Preview Network = "preview" - Preprod Network = "preprod" - Mainnet Network = "mainnet" -) - -var AllNetworks = []Network{Testnet, Preview, Preprod, Mainnet} - -func (n Network) String() string { - return string(n) -} - -func IsNetwork(value string) bool { - for _, network := range AllNetworks { - if value == network.String() { - return true - } - } - return false -} diff --git a/models/protocol.go b/models/protocol.go deleted file mode 100644 index 25abab0..0000000 --- a/models/protocol.go +++ /dev/null @@ -1,25 +0,0 @@ -package models - -type Protocol struct { - Epoch int - MinFeeA int - MinFeeB int - MaxBlockSize int - MaxTxSize int - MaxBlockHeaderSize int - KeyDeposit int - PoolDeposit int - Decentralisation float64 - MinPoolCost string - PriceMem float64 - PriceStep float64 - MaxTxExMem string - MaxTxExSteps string - MaxBlockExMem string - MaxBlockExSteps string - MaxValSize int - CollateralPercent int - MaxCollateralInputs int - CoinsPerUtxoSize int - MinFeeRefScriptCostPerByte int -} diff --git a/models/transaction_info.go b/models/transaction_info.go deleted file mode 100644 index 66b12aa..0000000 --- a/models/transaction_info.go +++ /dev/null @@ -1,13 +0,0 @@ -package models - -type TransactionInfo struct { - Index int - Block string - Hash string - Slot string - Fees string - Size int - Deposit string - InvalidBefore string - InvalidAfter string -} diff --git a/models/utxo.go b/models/utxo.go deleted file mode 100644 index 346ec11..0000000 --- a/models/utxo.go +++ /dev/null @@ -1,35 +0,0 @@ -package models - -type Input struct { - OutputIndex int `json:"output_index" binding:"required"` - TxHash string `json:"tx_hash" binding:"required"` -} - -type Output struct { - Address string `json:"address" binding:"required"` - Amount []Asset `json:"amount" binding:"required"` - DataHash string `json:"data_hash,omitempty"` - PlutusData string `json:"plutus_data,omitempty"` - ScriptRef string `json:"script_ref,omitempty"` - ScriptHash string `json:"script_hash,omitempty"` -} - -type UTxO struct { - Input Input `json:"input" binding:"required"` - Output Output `json:"output" binding:"required"` -} - -func MakeScriptUtxo(txHash string, outputIndex int, address string, amount []Asset, plutusData string, dataHash string) UTxO { - return UTxO{ - Input: Input{ - OutputIndex: outputIndex, - TxHash: txHash, - }, - Output: Output{ - Address: address, - Amount: amount, - DataHash: dataHash, - PlutusData: plutusData, - }, - } -} diff --git a/models/value.go b/models/value.go deleted file mode 100644 index 545f7b8..0000000 --- a/models/value.go +++ /dev/null @@ -1,108 +0,0 @@ -package models - -import ( - "strconv" -) - -type Value struct { - Value map[string]int64 -} - -func NewValue() *Value { - return &Value{ - Value: make(map[string]int64), - } -} - -func (mv *Value) AddAsset(asset Asset) { - quantity, _ := strconv.ParseInt(asset.Quantity, 10, 64) - if existingQuantity, exists := mv.Value[asset.Unit]; exists { - mv.Value[asset.Unit] = existingQuantity + quantity - } else { - mv.Value[asset.Unit] = quantity - } -} - -func (mv *Value) AddAssets(assets []Asset) { - for _, asset := range assets { - mv.AddAsset(asset) - } -} - -func (mv *Value) NegateAsset(asset Asset) { - quantity, _ := strconv.ParseInt(asset.Quantity, 10, 64) - if existingQuantity, exists := mv.Value[asset.Unit]; exists { - newQuantity := existingQuantity - quantity - if newQuantity == 0 { - delete(mv.Value, asset.Unit) - } else { - mv.Value[asset.Unit] = newQuantity - } - } -} - -func (mv *Value) NegateAssets(assets []Asset) { - for _, asset := range assets { - mv.NegateAsset(asset) - } -} - -func (mv *Value) Get(unit string) int64 { - if quantity, exists := mv.Value[unit]; exists { - return quantity - } - return 0 -} - -func (mv *Value) Units() []string { - units := make([]string, 0, len(mv.Value)) - for unit := range mv.Value { - units = append(units, unit) - } - return units -} - -func (mv *Value) IsEmpty() bool { - return len(mv.Value) == 0 -} - -func (mv *Value) Merge(values ...*Value) { - for _, other := range values { - if other == nil { - continue - } - for unit, quantity := range other.Value { - if existingQuantity, exists := mv.Value[unit]; exists { - mv.Value[unit] = existingQuantity + quantity - } else { - mv.Value[unit] = quantity - } - } - } -} - -func (mv *Value) ToAssets() *[]Asset { - assets := make([]Asset, 0, len(mv.Value)) - for unit, quantity := range mv.Value { - assets = append(assets, Asset{ - Unit: unit, - Quantity: strconv.FormatInt(quantity, 10), - }) - } - return &assets -} - -func (mv *Value) Geq(other *Value) bool { - for unit, quantity := range other.Value { - if existingQuantity, exists := mv.Value[unit]; !exists || existingQuantity < quantity { - return false - } - } - return true -} - -func FromAssets(assets []Asset) *Value { - mv := NewValue() - mv.AddAssets(assets) - return mv -} diff --git a/models/asset_test.go b/tests/asset_test.go similarity index 69% rename from models/asset_test.go rename to tests/asset_test.go index 941a1ac..8d19ae5 100644 --- a/models/asset_test.go +++ b/tests/asset_test.go @@ -1,41 +1,28 @@ -package models_test +package rum_test import ( "reflect" "testing" - "github.com/sidan-lab/rum/models" + "github.com/sidan-lab/rum" ) -// func (a *Assets) GetLovelace() uint64 { -// if a == nil { -// return 0 -// } -// for _, asset := range *a { -// if asset.Unit == "lovelace" { -// quantity, _ := strconv.ParseUint(asset.Quantity, 10, 64) -// return quantity -// } -// } -// return 0 -// } - func TestGetLovelace(t *testing.T) { - assets := models.Assets{ + assets := rum.Assets{ {Unit: "lovelace", Quantity: "100"}, {Unit: "USD", Quantity: "100"}, } if assets.GetLovelace() != 100 { t.Errorf("Expected 100, got %d", assets.GetLovelace()) } - assets = models.Assets{ + assets = rum.Assets{ {Unit: "USD", Quantity: "100"}, } if assets.GetLovelace() != 0 { t.Errorf("Expected 0, got %d", assets.GetLovelace()) } - var nilAssets models.Assets + var nilAssets rum.Assets if nilAssets.GetLovelace() != 0 { t.Errorf("Expected 0, got %d", nilAssets.GetLovelace()) } @@ -45,35 +32,35 @@ func TestPopAssetByUnit(t *testing.T) { // Define test cases tests := []struct { name string - initialAssets models.Assets + initialAssets rum.Assets unitToPop string - expectedAsset *models.Asset - expectedAssets models.Assets + expectedAsset *rum.Asset + expectedAssets rum.Assets }{ { name: "Pop existing asset", - initialAssets: models.Assets{ + initialAssets: rum.Assets{ {Unit: "lovelace", Quantity: "1000"}, {Unit: "asset1", Quantity: "2000"}, {Unit: "asset2", Quantity: "3000"}, }, unitToPop: "asset1", - expectedAsset: &models.Asset{Unit: "asset1", Quantity: "2000"}, - expectedAssets: models.Assets{ + expectedAsset: &rum.Asset{Unit: "asset1", Quantity: "2000"}, + expectedAssets: rum.Assets{ {Unit: "lovelace", Quantity: "1000"}, {Unit: "asset2", Quantity: "3000"}, }, }, { name: "Pop non-existing asset", - initialAssets: models.Assets{ + initialAssets: rum.Assets{ {Unit: "lovelace", Quantity: "1000"}, {Unit: "asset1", Quantity: "2000"}, {Unit: "asset2", Quantity: "3000"}, }, unitToPop: "asset3", - expectedAsset: &models.Asset{}, - expectedAssets: models.Assets{ + expectedAsset: &rum.Asset{}, + expectedAssets: rum.Assets{ {Unit: "lovelace", Quantity: "1000"}, {Unit: "asset1", Quantity: "2000"}, {Unit: "asset2", Quantity: "3000"}, diff --git a/providers/blockfrost_test.go b/tests/blockfrost_test.go similarity index 67% rename from providers/blockfrost_test.go rename to tests/blockfrost_test.go index 64916fe..d3792bf 100644 --- a/providers/blockfrost_test.go +++ b/tests/blockfrost_test.go @@ -1,26 +1,25 @@ -package providers_test +package rum_test import ( "fmt" "os" "testing" - "github.com/sidan-lab/rum/interfaces" - "github.com/sidan-lab/rum/providers" + "github.com/sidan-lab/rum" ) func TestBlockfrostProviderImplementsIFetcher(t *testing.T) { - var _ interfaces.IFetcher = (*providers.BlockfrostProvider)(nil) + var _ rum.IFetcher = (*rum.BlockfrostProvider)(nil) } func TestBlockfrostProviderImplementsISubmitter(t *testing.T) { - var _ interfaces.ISubmitter = (*providers.BlockfrostProvider)(nil) + var _ rum.ISubmitter = (*rum.BlockfrostProvider)(nil) } func TestBlockfrostFetchTxInfo(t *testing.T) { Init(t) txHash := confirmedTxHash // txHash = unconfirmedTxHash - blockfrost := providers.NewBlockfrostProvider(os.Getenv("BLOCKFROST_PROJECT_ID")) + blockfrost := rum.NewBlockfrostProvider(os.Getenv("BLOCKFROST_PROJECT_ID")) res, err := blockfrost.FetchTxInfo(txHash) if err != nil { fmt.Println("failed to fetch tx") @@ -32,7 +31,7 @@ func TestBlockfrostFetchTxInfo(t *testing.T) { func TestBlockfrostFetchUtxos(t *testing.T) { Init(t) txHash := "4d2545880f6a6518e6b273875882089c9f3f9955cb3623e9222047e98fc7d1fe" - blockfrost := providers.NewBlockfrostProvider(os.Getenv("BLOCKFROST_PROJECT_ID")) + blockfrost := rum.NewBlockfrostProvider(os.Getenv("BLOCKFROST_PROJECT_ID")) utxos, err := blockfrost.FetchUTxOs(txHash, nil) if err != nil { fmt.Println("failed to fetch utxos") diff --git a/providers/maestro_test.go b/tests/maestro_test.go similarity index 72% rename from providers/maestro_test.go rename to tests/maestro_test.go index f4a8cab..13a334b 100644 --- a/providers/maestro_test.go +++ b/tests/maestro_test.go @@ -1,4 +1,4 @@ -package providers_test +package rum_test import ( "fmt" @@ -6,10 +6,7 @@ import ( "testing" "github.com/lpernett/godotenv" - - "github.com/sidan-lab/rum/interfaces" - "github.com/sidan-lab/rum/models" - "github.com/sidan-lab/rum/providers" + "github.com/sidan-lab/rum" ) const confirmedTxHash = "5101ee2bac21b7e8d7409ee95aeec1444f294248ae85a98c88bbba640cbd132d" @@ -23,10 +20,10 @@ func Init(t *testing.T) { } func TestMaestroProviderImplementsIFetcher(t *testing.T) { - var _ interfaces.IFetcher = (*providers.MaestroProvider)(nil) + var _ rum.IFetcher = (*rum.MaestroProvider)(nil) } func TestMaestroProviderImplementsISubmitter(t *testing.T) { - var _ interfaces.ISubmitter = (*providers.MaestroProvider)(nil) + var _ rum.ISubmitter = (*rum.MaestroProvider)(nil) } func TestMaestroFetchTxInfo(t *testing.T) { @@ -34,7 +31,7 @@ func TestMaestroFetchTxInfo(t *testing.T) { txHash := confirmedTxHash txHash = unconfirmedTxHash network := os.Getenv("NETWORK") - maestro := providers.NewMaestroProvider(os.Getenv("MAESTRO_API_KEY"), models.Network(network)) + maestro := rum.NewMaestroProvider(os.Getenv("MAESTRO_API_KEY"), rum.Network(network)) _, err := maestro.FetchTxInfo(txHash) if err != nil { fmt.Println("failed to fetch tx") @@ -46,7 +43,7 @@ func TestMaestroFetchUtxos(t *testing.T) { Init(t) txHash := "4d2545880f6a6518e6b273875882089c9f3f9955cb3623e9222047e98fc7d1fe" network := os.Getenv("NETWORK") - maestro := providers.NewMaestroProvider(os.Getenv("MAESTRO_API_KEY"), models.Network(network)) + maestro := rum.NewMaestroProvider(os.Getenv("MAESTRO_API_KEY"), rum.Network(network)) utxos, err := maestro.FetchUTxOs(txHash, nil) if err != nil { fmt.Println("failed to fetch utxos") diff --git a/models/value_test.go b/tests/value_test.go similarity index 74% rename from models/value_test.go rename to tests/value_test.go index 816a1b9..c585c6c 100644 --- a/models/value_test.go +++ b/tests/value_test.go @@ -1,27 +1,25 @@ -package models +package rum_test import ( "testing" + + "github.com/sidan-lab/rum" ) func TestAddAsset(t *testing.T) { - mv := NewValue() - asset := Asset{Unit: "USD", Quantity: "100"} - mv.AddAsset(asset) - + asset := rum.Asset{Unit: "USD", Quantity: "100"} + mv := rum.NewValue().AddAsset(&asset) if mv.Get("USD") != 100 { t.Errorf("Expected 100, got %d", mv.Get("USD")) } } func TestAddAssets(t *testing.T) { - mv := NewValue() - assets := []Asset{ + assets := []rum.Asset{ {Unit: "USD", Quantity: "100"}, {Unit: "EUR", Quantity: "200"}, } - mv.AddAssets(assets) - + mv := rum.NewValue().AddAssets(&assets) if mv.Get("USD") != 100 { t.Errorf("Expected 100, got %d", mv.Get("USD")) } @@ -31,10 +29,8 @@ func TestAddAssets(t *testing.T) { } func TestNegateAsset(t *testing.T) { - mv := NewValue() - asset := Asset{Unit: "USD", Quantity: "100"} - mv.AddAsset(asset) - mv.NegateAsset(asset) + asset := rum.Asset{Unit: "USD", Quantity: "100"} + mv := rum.NewValue().AddAsset(&asset).NegateAsset(&asset) if mv.Get("USD") != 0 { t.Errorf("Expected 0, got %d", mv.Get("USD")) @@ -42,14 +38,11 @@ func TestNegateAsset(t *testing.T) { } func TestNegateAssets(t *testing.T) { - mv := NewValue() - assets := []Asset{ + assets := []rum.Asset{ {Unit: "USD", Quantity: "100"}, {Unit: "EUR", Quantity: "200"}, } - mv.AddAssets(assets) - mv.NegateAssets(assets) - + mv := rum.NewValue().AddAssets(&assets).NegateAssets(&assets) if mv.Get("USD") != 0 { t.Errorf("Expected 0, got %d", mv.Get("USD")) } @@ -59,20 +52,16 @@ func TestNegateAssets(t *testing.T) { } func TestMerge(t *testing.T) { - mv1 := NewValue() - mv2 := NewValue() - mv1.AddAsset(Asset{Unit: "USD", Quantity: "100"}) - mv2.AddAsset(Asset{Unit: "USD", Quantity: "200"}) - mv1.Merge(mv2) - - if mv1.Get("USD") != 300 { + mv1 := rum.NewValue().AddAsset(&rum.Asset{Unit: "USD", Quantity: "100"}) + mv2 := rum.NewValue().AddAsset(&rum.Asset{Unit: "USD", Quantity: "200"}).Merge(mv1) + if mv2.Get("USD") != 300 { t.Errorf("Expected 300, got %d", mv1.Get("USD")) } } func TestMergeNil(t *testing.T) { - mv1 := NewValue() - mv1.AddAsset(Asset{Unit: "USD", Quantity: "100"}) + mv1 := rum.NewValue() + mv1.AddAsset(&rum.Asset{Unit: "USD", Quantity: "100"}) mv1.Merge(nil) if mv1.Get("USD") != 100 { @@ -81,10 +70,10 @@ func TestMergeNil(t *testing.T) { } func TestMergeFromNewMap(t *testing.T) { - mv1 := NewValue() - mv1.AddAsset(Asset{Unit: "USD", Quantity: "100"}) + mv1 := rum.NewValue() + mv1.AddAsset(&rum.Asset{Unit: "USD", Quantity: "100"}) - mv2 := NewValue() + mv2 := rum.NewValue() mv2.Merge(mv1) if mv1.Get("USD") != 100 { @@ -93,8 +82,8 @@ func TestMergeFromNewMap(t *testing.T) { } func TestToAssets(t *testing.T) { - mv := NewValue() - mv.AddAsset(Asset{Unit: "USD", Quantity: "100"}) + mv := rum.NewValue() + mv.AddAsset(&rum.Asset{Unit: "USD", Quantity: "100"}) assets := *mv.ToAssets() if len(assets) != 1 { @@ -106,11 +95,11 @@ func TestToAssets(t *testing.T) { } func TestFromAssets(t *testing.T) { - assets := []Asset{ + assets := []rum.Asset{ {Unit: "USD", Quantity: "100"}, {Unit: "EUR", Quantity: "200"}, } - mv := FromAssets(assets) + mv := rum.NewValueFromAssets(&assets) if mv.Get("USD") != 100 { t.Errorf("Expected 100, got %d", mv.Get("USD")) @@ -124,19 +113,19 @@ func TestGeq(t *testing.T) { // Define test cases tests := []struct { name string - value1 *Value - value2 *Value + value1 *rum.Value + value2 *rum.Value expected bool }{ { name: "Value1 greater than or equal to Value2", - value1: &Value{ + value1: &rum.Value{ Value: map[string]int64{ "asset1": 1000, "asset2": 2000, }, }, - value2: &Value{ + value2: &rum.Value{ Value: map[string]int64{ "asset1": 500, "asset2": 1500, @@ -146,13 +135,13 @@ func TestGeq(t *testing.T) { }, { name: "Value1 less than Value2", - value1: &Value{ + value1: &rum.Value{ Value: map[string]int64{ "asset1": 1000, "asset2": 1000, }, }, - value2: &Value{ + value2: &rum.Value{ Value: map[string]int64{ "asset1": 1500, "asset2": 1500, @@ -162,13 +151,13 @@ func TestGeq(t *testing.T) { }, { name: "Value1 equal to Value2", - value1: &Value{ + value1: &rum.Value{ Value: map[string]int64{ "asset1": 1000, "asset2": 2000, }, }, - value2: &Value{ + value2: &rum.Value{ Value: map[string]int64{ "asset1": 1000, "asset2": 2000, @@ -178,14 +167,14 @@ func TestGeq(t *testing.T) { }, { name: "Value1 has more assets than Value2", - value1: &Value{ + value1: &rum.Value{ Value: map[string]int64{ "asset1": 1000, "asset2": 2000, "asset3": 3000, }, }, - value2: &Value{ + value2: &rum.Value{ Value: map[string]int64{ "asset1": 1000, "asset2": 2000, @@ -195,12 +184,12 @@ func TestGeq(t *testing.T) { }, { name: "Value1 has fewer assets than Value2", - value1: &Value{ + value1: &rum.Value{ Value: map[string]int64{ "asset1": 1000, }, }, - value2: &Value{ + value2: &rum.Value{ Value: map[string]int64{ "asset1": 1000, "asset2": 2000, @@ -210,13 +199,13 @@ func TestGeq(t *testing.T) { }, { name: "Value1 has fewer assets than Value2", - value1: &Value{ + value1: &rum.Value{ Value: map[string]int64{ "asset1": 1500, "asset2": 1500, }, }, - value2: &Value{ + value2: &rum.Value{ Value: map[string]int64{ "asset1": 1000, "asset2": 2000, diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..1a5c359 --- /dev/null +++ b/utils.go @@ -0,0 +1,10 @@ +package rum + +func FindUtxoByIndex(utxos []UTxO, index int) *UTxO { + for _, utxo := range utxos { + if utxo.Input.OutputIndex == index { + return &utxo + } + } + return nil +} diff --git a/utils/utils.go b/utils/utils.go deleted file mode 100644 index 0775784..0000000 --- a/utils/utils.go +++ /dev/null @@ -1,12 +0,0 @@ -package utils - -import "github.com/sidan-lab/rum/models" - -func FindUtxoByIndex(utxos []models.UTxO, index int) *models.UTxO { - for _, utxo := range utxos { - if utxo.Input.OutputIndex == index { - return &utxo - } - } - return nil -} diff --git a/value.go b/value.go new file mode 100644 index 0000000..f549efa --- /dev/null +++ b/value.go @@ -0,0 +1,126 @@ +package rum + +import ( + "strconv" +) + +type Value struct { + Value map[string]int64 +} + +func NewValue() *Value { + return &Value{ + Value: make(map[string]int64), + } +} + +func NewValueFromAssets(assets *[]Asset) *Value { + value := &Value{ + Value: make(map[string]int64), + } + if assets == nil { + return value + } + return value.AddAssets(assets) +} + +func (v *Value) AddAsset(asset *Asset) *Value { + quantity, _ := strconv.ParseInt(asset.Quantity, 10, 64) + if existingQuantity, exists := v.Value[asset.Unit]; exists { + v.Value[asset.Unit] = existingQuantity + quantity + } else { + v.Value[asset.Unit] = quantity + } + return v +} + +func (v *Value) AddAssets(assets *[]Asset) *Value { + if assets == nil { + return v + } + for _, asset := range *assets { + v.AddAsset(&asset) + } + return v +} + +func (v *Value) NegateAsset(asset *Asset) *Value { + if asset == nil { + return v + } + quantity, _ := strconv.ParseInt(asset.Quantity, 10, 64) + if existingQuantity, exists := v.Value[asset.Unit]; exists { + newQuantity := existingQuantity - quantity + if newQuantity == 0 { + delete(v.Value, asset.Unit) + } else { + v.Value[asset.Unit] = newQuantity + } + } + return v +} + +func (v *Value) NegateAssets(assets *[]Asset) *Value { + if assets == nil { + return v + } + for _, asset := range *assets { + v.NegateAsset(&asset) + } + return v +} + +func (v *Value) Merge(values ...*Value) *Value { + for _, other := range values { + if other == nil { + continue + } + for unit, quantity := range other.Value { + if existingQuantity, exists := v.Value[unit]; exists { + v.Value[unit] = existingQuantity + quantity + } else { + v.Value[unit] = quantity + } + } + } + return v +} + +func (v *Value) Get(unit string) int64 { + if quantity, exists := v.Value[unit]; exists { + return quantity + } + return 0 +} + +func (v *Value) Units() []string { + units := make([]string, 0, len(v.Value)) + for unit := range v.Value { + units = append(units, unit) + } + return units +} + +func (v *Value) IsEmpty() bool { + return len(v.Value) == 0 +} + +func (v *Value) ToAssets() *[]Asset { + assets := make([]Asset, 0, len(v.Value)) + for unit, quantity := range v.Value { + assets = append(assets, Asset{ + Unit: unit, + Quantity: strconv.FormatInt(quantity, 10), + }) + } + return &assets +} + +func (v *Value) Geq(other *Value) bool { + for unit, quantity := range other.Value { + if existingQuantity, exists := v.Value[unit]; !exists || existingQuantity < quantity { + return false + } + } + return true +}