diff --git a/CHANGELOG.md b/CHANGELOG.md index d3d995d1..7c2e9be5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 1.8.0 +# Added +- V2: Add MakeClientWithHeaders wrapper functions +# Bugfix +- Fix FlatFee computation # 1.7.0 # Bugfix - Fix GetGenesis endpoint. diff --git a/client/v2/algod/algod.go b/client/v2/algod/algod.go index b788e049..c96351ff 100644 --- a/client/v2/algod/algod.go +++ b/client/v2/algod/algod.go @@ -40,6 +40,12 @@ func MakeClient(address string, apiToken string) (c *Client, err error) { return } +func MakeClientWithHeaders(address string, apiToken string, headers []*common.Header) (c *Client, err error) { + commonClientWithHeaders, err := common.MakeClientWithHeaders(address, authHeader, apiToken, headers) + c = (*Client)(commonClientWithHeaders) + return +} + func (c *Client) HealthCheck() *HealthCheck { return &HealthCheck{c: c} } diff --git a/client/v2/indexer/indexer.go b/client/v2/indexer/indexer.go index 731c28c1..d9ad0eb2 100644 --- a/client/v2/indexer/indexer.go +++ b/client/v2/indexer/indexer.go @@ -39,6 +39,12 @@ func MakeClient(address string, apiToken string) (c *Client, err error) { return } +func MakeClientWithHeaders(address string, apiToken string, headers []*common.Header) (c *Client, err error) { + commonClientWithHeaders, err := common.MakeClientWithHeaders(address, authHeader, apiToken, headers) + c = (*Client)(commonClientWithHeaders) + return +} + func (c *Client) HealthCheck() *HealthCheck { return &HealthCheck{c: c} } diff --git a/future/transaction.go b/future/transaction.go index cd55f98e..c926e839 100644 --- a/future/transaction.go +++ b/future/transaction.go @@ -11,6 +11,24 @@ import ( // MinTxnFee is v5 consensus params, in microAlgos const MinTxnFee = transaction.MinTxnFee +func setFee(tx types.Transaction, params types.SuggestedParams) (types.Transaction, error) { + if !params.FlatFee { + eSize, err := transaction.EstimateSize(tx) + if err != nil { + return types.Transaction{}, err + } + tx.Fee = types.MicroAlgos(eSize * uint64(params.Fee)) + } else { + tx.Fee = params.Fee + } + + if tx.Fee < MinTxnFee { + tx.Fee = MinTxnFee + } + + return tx, nil +} + // MakePaymentTxn constructs a payment transaction using the passed parameters. // `from` and `to` addresses should be checksummed, human-readable addresses // fee is fee per byte as received from algod SuggestedFee API call @@ -62,20 +80,7 @@ func MakePaymentTxn(from, to string, amount uint64, note []byte, closeRemainderT }, } - // Update fee - if !params.FlatFee { - eSize, err := transaction.EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * uint64(params.Fee)) - } - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil + return setFee(tx, params) } // MakeKeyRegTxn constructs a keyreg transaction using the passed parameters. @@ -132,20 +137,7 @@ func MakeKeyRegTxn(account string, note []byte, params types.SuggestedParams, vo }, } - if !params.FlatFee { - // Update fee - eSize, err := transaction.EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * uint64(params.Fee)) - } - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil + return setFee(tx, params) } // MakeAssetCreateTxn constructs an asset creation transaction using the passed parameters. @@ -240,19 +232,7 @@ func MakeAssetCreateTxn(account string, note []byte, params types.SuggestedParam } // Update fee - if !params.FlatFee { - eSize, err := transaction.EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * uint64(params.Fee)) - } - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil + return setFee(tx, params) } // MakeAssetConfigTxn creates a tx template for changing the @@ -329,20 +309,8 @@ func MakeAssetConfigTxn(account string, note []byte, params types.SuggestedParam } } - if !params.FlatFee { - // Update fee - eSize, err := transaction.EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * uint64(params.Fee)) - } - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil + // Update fee + return setFee(tx, params) } // transferAssetBuilder is a helper that builds asset transfer transactions: @@ -398,18 +366,9 @@ func transferAssetBuilder(account, recipient string, amount uint64, note []byte, tx.AssetAmount = amount - // Update fee - eSize, err := transaction.EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * uint64(params.Fee)) - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - return tx, nil + // Update fee + return setFee(tx, params) } // MakeAssetTransferTxn creates a tx for sending some asset from an asset holder to another user @@ -500,20 +459,8 @@ func MakeAssetFreezeTxn(account string, note []byte, params types.SuggestedParam tx.AssetFrozen = newFreezeSetting - if !params.FlatFee { - // Update fee - eSize, err := transaction.EstimateSize(tx) - if err != nil { - return types.Transaction{}, err - } - tx.Fee = types.MicroAlgos(eSize * uint64(params.Fee)) - } - - if tx.Fee < MinTxnFee { - tx.Fee = MinTxnFee - } - - return tx, nil + // Update fee + return setFee(tx, params) } // byte32FromBase64 decodes the input base64 string and outputs a @@ -843,24 +790,10 @@ func MakeApplicationCallTx( tx.LocalStateSchema = localSchema tx.GlobalStateSchema = globalSchema - setApplicationTransactionFields(&tx, sp, sender, note, group, lease, rekeyTo) - - return tx, nil -} - -func setApplicationTransactionFields( - applicationTransaction *types.Transaction, - sp types.SuggestedParams, - sender types.Address, - note []byte, - group types.Digest, - lease [32]byte, - rekeyTo types.Address) error { - var gh types.Digest copy(gh[:], sp.GenesisHash) - applicationTransaction.Header = types.Header{ + tx.Header = types.Header{ Sender: sender, Fee: sp.Fee, FirstValid: sp.FirstRoundValid, @@ -873,19 +806,8 @@ func setApplicationTransactionFields( RekeyTo: rekeyTo, } - if !sp.FlatFee { - // Update fee - eSize, err := transaction.EstimateSize(*applicationTransaction) - if err != nil { - return err - } - applicationTransaction.Fee = types.MicroAlgos(eSize * uint64(sp.Fee)) - } - - if applicationTransaction.Fee < MinTxnFee { - applicationTransaction.Fee = MinTxnFee - } - return nil + // Update fee + return setFee(tx, sp) } func parseTxnAccounts(accounts []string) (parsed []types.Address, err error) { diff --git a/future/transaction_test.go b/future/transaction_test.go index fa802914..99a0e948 100644 --- a/future/transaction_test.go +++ b/future/transaction_test.go @@ -725,5 +725,75 @@ func TestLogicSig(t *testing.T) { verified := crypto.VerifyLogicSig(lsig, sender) require.True(t, verified) +} +func TestFee(t *testing.T) { + testcases := []struct { + name string + flatFee bool + fee types.MicroAlgos + expected types.MicroAlgos + }{ + { + name: "Use flat fee", + flatFee: true, + fee: 1001, + expected: 1001, + }, + { + name: "Flat fee overridden with min fee", + flatFee: true, + fee: 999, + expected: 1000, + }, + { + name: "Estimated fee overridden with min fee", + flatFee: false, + fee: 1, + expected: 1000, + }, + } + addr := types.Address{}.String() + for _, testcase := range testcases { + t.Run(testcase.name, func(t *testing.T) { + var tx types.Transaction + var err error + + params := types.SuggestedParams{ + FlatFee: testcase.flatFee, + Fee: testcase.fee, + FirstRoundValid: 1, + LastRoundValid: 1001, + GenesisHash: byteFromBase64("JgsgCaCTqIaLeVhyL6XlRu3n7Rfk2FxMeK+wRSaQ7dI="), + } + + tx, err = MakeAssetTransferTxn(addr, addr, 1, nil, params, "", 1) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetAcceptanceTxn(addr, nil, params, 1) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetRevocationTxn(addr, addr, 1, addr, nil, params, 1) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetDestroyTxn(addr, nil, params, 1) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetCreateTxn(addr, nil, params, 1, 1, false, addr, addr, addr, addr, "", "", "", "") + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetConfigTxn(addr, nil, params, 1, addr, addr, addr, addr, false) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + + tx, err = MakeAssetFreezeTxn(addr, nil, params, 1, addr, true) + require.NoError(t, err) + require.Equal(t, testcase.expected, tx.Fee) + }) + } }