Skip to content

Commit

Permalink
Various updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
mcdee committed Nov 18, 2024
1 parent e949010 commit 7cd0510
Show file tree
Hide file tree
Showing 26 changed files with 1,017 additions and 409 deletions.
33 changes: 33 additions & 0 deletions api/estimatefeeopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright © 2024 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
"github.com/attestantio/go-starknet-client/spec"
"github.com/attestantio/go-starknet-client/types"
)

// EstimateFeeOpts are the options for estimating fees for a transaction.
type EstimateFeeOpts struct {
Common CommonOpts

// Block is the block at which the fee is estimated.
// It can be a block number, block hash, or one of the special values "latest" or "pending".
Block types.BlockID

// Transaction is the transaction for which to estimate fees.
Transaction *spec.Transaction

// Simulation flags?
}
41 changes: 41 additions & 0 deletions api/feeestimate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright © 2024 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
"encoding/json"
"fmt"

"github.com/attestantio/go-starknet-client/types"
)

// FeeEstimate contains a fee estimate.
type FeeEstimate struct {
GasConsumed types.Number `json:"gas_consumed"`
GasPrice types.Number `json:"gas_price"`
DataGasConsumed types.Number `json:"data_gas_consumed"`
DataGasPrice types.Number `json:"data_gas_price"`
OverallFee types.Number `json:"overall_fee"`
Unit string `json:"unit"`
}

// String returns a string version of the structure.
func (f *FeeEstimate) String() string {
data, err := json.Marshal(f)
if err != nil {
return fmt.Sprintf("ERR: %v", err)
}

return string(data)
}
26 changes: 26 additions & 0 deletions api/submittransactionopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright © 2024 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
"github.com/attestantio/go-starknet-client/spec"
)

// SubmitTransactionOpts are the options for transactions.
type SubmitTransactionOpts struct {
Common CommonOpts

// Transaction is the transaction to send.
Transaction *spec.Transaction
}
36 changes: 36 additions & 0 deletions api/submittransactionresponse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright © 2024 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
"encoding/json"
"fmt"

"github.com/attestantio/go-starknet-client/types"
)

// SubmitTransactionResponse is the response from SubmitTransaction.
type SubmitTransactionResponse struct {
TransactionHash types.Hash `json:"transaction_hash"`
}

// String returns a string version of the structure.
func (t SubmitTransactionResponse) String() string {
data, err := json.Marshal(t)
if err != nil {
return fmt.Sprintf("ERR: %v", err)
}

return string(data)
}
55 changes: 55 additions & 0 deletions jsonrpc/estimatefee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright © 2024 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package jsonrpc

import (
"context"
"errors"

client "github.com/attestantio/go-starknet-client"
"github.com/attestantio/go-starknet-client/api"
)

// EstimateFee estimates the fee for a transaction.
func (s *Service) EstimateFee(ctx context.Context,
opts *api.EstimateFeeOpts,
) (
*api.Response[[]api.FeeEstimate],
error,
) {
if err := s.assertIsSynced(ctx); err != nil {
return nil, err
}

if opts == nil {
return nil, client.ErrNoOptions
}
if opts.Transaction == nil {
return nil, errors.Join(errors.New("no transaction specified"), client.ErrInvalidOptions)
}

tx := preFlightTransaction(ctx, opts.Transaction)
tx.SetQueryBit()

var data []api.FeeEstimate
err := s.client.CallFor(&data, "starknet_estimateFee", []any{tx}, []any{"SKIP_VALIDATE"}, opts.Block)
if err != nil {
return nil, errors.Join(errors.New("starknet_estimateFee failed"), err)
}

return &api.Response[[]api.FeeEstimate]{
Data: data,
Metadata: map[string]any{},
}, nil
}
109 changes: 109 additions & 0 deletions jsonrpc/estimatefee_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright © 2024 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package jsonrpc_test

import (
"context"
"os"
"testing"

"github.com/attestantio/go-starknet-client/api"
"github.com/attestantio/go-starknet-client/jsonrpc"
"github.com/attestantio/go-starknet-client/spec"
"github.com/attestantio/go-starknet-client/types"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
)

func TestEstimateFee(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

s, err := jsonrpc.New(ctx,
jsonrpc.WithLogLevel(zerolog.Disabled),
jsonrpc.WithAddress(os.Getenv("JSONRPC_ADDRESS")),
jsonrpc.WithTimeout(timeout),
)
require.NoError(t, err)

nonceResponse, err := s.Nonce(ctx, &api.NonceOpts{
Block: "latest",
Contract: strToAddress("0x391d69afc1b49f01ad8d2e0e8a03756b694dd056fb6645781eb00f33dbd8caf"),
})
require.NoError(t, err)

tests := []struct {
name string
transaction *spec.Transaction
}{
{
name: "InvokeV1",
transaction: &spec.Transaction{
InvokeV1Transaction: &spec.InvokeV1Transaction{
Type: spec.TransactionTypeInvoke,
SenderAddress: strToAddress("0x391d69afc1b49f01ad8d2e0e8a03756b694dd056fb6645781eb00f33dbd8caf"),
Calldata: []types.FieldElement{
strToFieldElement("0x1"),
strToFieldElement("0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"),
strToFieldElement("0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e"),
strToFieldElement("0x3"),
strToFieldElement("0x714792a41f3651e171c46c93fc53adeb922a414a891cc36d73029d23e99a6ec"),
strToFieldElement("0x2386f26fc10000"),
strToFieldElement("0x0"),
},
Version: spec.TransactionVersion1,
Signature: types.Signature{},
Nonce: types.Number(nonceResponse.Data),
MaxFee: 1000000000000,
},
},
},
{
name: "InvokeV3",
transaction: &spec.Transaction{
InvokeV3Transaction: &spec.InvokeV3Transaction{
Type: spec.TransactionTypeInvoke,
SenderAddress: strToAddress("0x391d69afc1b49f01ad8d2e0e8a03756b694dd056fb6645781eb00f33dbd8caf"),
Calldata: []types.FieldElement{
strToFieldElement("0x1"),
strToFieldElement("0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"),
strToFieldElement("0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e"),
strToFieldElement("0x3"),
strToFieldElement("0x714792a41f3651e171c46c93fc53adeb922a414a891cc36d73029d23e99a6ec"),
strToFieldElement("0x2386f26fc10000"),
strToFieldElement("0x0"),
},
Version: spec.TransactionVersion3,
Signature: types.Signature{},
Nonce: types.Number(nonceResponse.Data),
ResourceBounds: spec.ResourceBounds{},
Tip: 0,
NonceDataAvailabilityMode: spec.TxDAModeL1,
FeeDataAvailabilityMode: spec.TxDAModeL1,
},
},
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
response, err := s.EstimateFee(ctx, &api.EstimateFeeOpts{
Block: "pending",
Transaction: test.transaction,
})
require.NoError(t, err)
require.NotNil(t, response.Data)
})
}
}
69 changes: 69 additions & 0 deletions jsonrpc/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright © 2024 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package jsonrpc

import (
"context"

"github.com/attestantio/go-starknet-client/spec"
"github.com/attestantio/go-starknet-client/types"
)

// preFlightTransaction tidies up a transaction before sending it to a client.
func preFlightTransaction(ctx context.Context,
tx *spec.Transaction,
) *spec.Transaction {
switch {
case tx.InvokeV1Transaction != nil:
return preFlightInvokeV1Transaction(ctx, tx)
case tx.InvokeV3Transaction != nil:
return preFlightInvokeV3Transaction(ctx, tx)
}

return tx
}

func preFlightInvokeV1Transaction(_ context.Context,
tx *spec.Transaction,
) *spec.Transaction {
cpTx := &spec.Transaction{
InvokeV1Transaction: tx.InvokeV1Transaction.Copy(),
}

if cpTx.InvokeV1Transaction.Signature == nil {
cpTx.InvokeV1Transaction.Signature = types.Signature{}
}

return cpTx
}

func preFlightInvokeV3Transaction(_ context.Context,
tx *spec.Transaction,
) *spec.Transaction {
cpTx := &spec.Transaction{
InvokeV3Transaction: tx.InvokeV3Transaction.Copy(),
}

if cpTx.InvokeV3Transaction.Signature == nil {
cpTx.InvokeV3Transaction.Signature = types.Signature{}
}
if cpTx.InvokeV3Transaction.PaymasterData == nil {
cpTx.InvokeV3Transaction.PaymasterData = []types.FieldElement{}
}
if cpTx.InvokeV3Transaction.AccountDeploymentData == nil {
cpTx.InvokeV3Transaction.AccountDeploymentData = []types.FieldElement{}
}

return cpTx
}
Loading

0 comments on commit 7cd0510

Please sign in to comment.