Skip to content

Commit

Permalink
Merge branch 'main' into ianthpun/main-to-stable
Browse files Browse the repository at this point in the history
  • Loading branch information
ianthpun committed Feb 16, 2024
2 parents b37ad30 + d6b4b66 commit 8549eb0
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 20 deletions.
39 changes: 39 additions & 0 deletions flowkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,45 @@ func (f *Flowkit) SendTransaction(
return sentTx, res, err
}

// ReplaceImportsInScript will replace the imports in the script code with the contracts from the network.
func (f *Flowkit) ReplaceImportsInScript(
ctx context.Context,
script Script,
) (Script, error) {
state, err := f.State()
if err != nil {
return Script{}, err
}

contracts, err := state.DeploymentContractsByNetwork(f.network)
if err != nil {
return Script{}, err
}

importReplacer := project.NewImportReplacer(
contracts,
state.AliasesForNetwork(f.network),
)

program, err := project.NewProgram(script.Code, script.Args, script.Location)
if err != nil {
return Script{}, err
}

if program.HasImports() {
program, err = importReplacer.Replace(program)
if err != nil {
return Script{}, err
}
}

return Script{
Code: program.Code(),
Args: script.Args,
Location: script.Location,
}, nil
}

// this is added to resolve the issue with chainhash ambiguous import,
// the code is not used, but it's needed to force go.mod specify and retain chainhash version
// workaround for issue: https://github.com/golang/go/issues/27899
Expand Down
39 changes: 39 additions & 0 deletions flowkit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,45 @@ func resourceToContract(res tests.Resource) Script {

var ctx = context.Background()

func TestReplaceImports(t *testing.T) {
t.Run("Replace Imports", func(t *testing.T) {
t.Parallel()

state, flowkit := setupIntegration()
srvAcc, _ := state.EmulatorServiceAccount()

// setup
c := config.Contract{
Name: tests.ContractHelloString.Name,
Location: tests.ContractHelloString.Filename,
}
state.Contracts().AddOrUpdate(c)
state.Networks().AddOrUpdate(config.EmulatorNetwork)

d := config.Deployment{
Network: config.EmulatorNetwork.Name,
Account: srvAcc.Name,
Contracts: []config.ContractDeployment{{
Name: c.Name,
Args: nil,
}},
}
state.Deployments().AddOrUpdate(d)
_, _, _ = flowkit.AddContract(
ctx,
srvAcc,
resourceToContract(tests.ContractHelloString),
UpdateExistingContract(false),
)

contract := resourceToContract(tests.ScriptImport)
contract, err := flowkit.ReplaceImportsInScript(ctx, contract)

assert.NoError(t, err)
assert.True(t, strings.Contains(string(contract.Code), "import Hello from 0x"))
})
}

func TestAccounts(t *testing.T) {
state, _, _ := setup()
pubKey, _ := crypto.DecodePublicKeyHex(crypto.ECDSA_P256, "858a7d978b25d61f348841a343f79131f4b9fab341dd8a476a6f4367c25510570bf69b795fc9c3d2b7191327d869bcf848508526a3c1cafd1af34f71c7765117")
Expand Down
1 change: 0 additions & 1 deletion gateway/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ func NewSecureGrpcGateway(network config.Network, opts ...grpc.DialOption) (*Grp
options...,
)


if err != nil || gClient == nil {
return nil, fmt.Errorf("failed to connect to host %s", network.Host)
}
Expand Down
28 changes: 28 additions & 0 deletions mocks/Services.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 1 addition & 19 deletions mocks/services_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
package mocks

import (
"context"

"github.com/onflow/cadence"
"github.com/onflow/flow-go-sdk"
"github.com/stretchr/testify/mock"
Expand Down Expand Up @@ -79,46 +77,39 @@ type MockServices struct {
}

func DefaultMockServices() *MockServices {
ctx := context.Background()
m := &Services{}
t := &MockServices{
Mock: m,
GetAccount: m.On(
mocks.GetAccountFunc,
ctx,
mock.Anything,
mock.AnythingOfType("flow.Address"),
),
ExecuteScript: m.On(
mocks.ExecuteScriptFunc,
ctx,
mock.Anything,
mock.AnythingOfType("flowkit.Script"),
mock.AnythingOfType("flowkit.ScriptQuery"),
),
SendSignedTransaction: m.On(
mocks.SendSignedTransactionFunc,
ctx,
mock.Anything,
mock.AnythingOfType("*transactions.Transaction"),
),
AddContract: m.On(
addContractFunc,
ctx,
mock.Anything,
mock.AnythingOfType("*accounts.Account"),
mock.AnythingOfType("flowkit.Script"),
mock.AnythingOfType("flowkit.UpdateContract"),
),
GetCollection: m.On(
mocks.GetCollectionFunc,
ctx,
mock.Anything,
mock.AnythingOfType("flow.Identifier"),
),
GetEvents: m.On(
mocks.GetEventsFunc,
ctx,
mock.Anything,
mock.AnythingOfType("[]string"),
mock.AnythingOfType("uint64"),
Expand All @@ -127,7 +118,6 @@ func DefaultMockServices() *MockServices {
),
BuildTransaction: m.On(
buildTransactionFunc,
ctx,
mock.Anything,
mock.AnythingOfType("transactions.AddressesRoles"),
mock.AnythingOfType("int"),
Expand All @@ -136,14 +126,12 @@ func DefaultMockServices() *MockServices {
),
CreateAccount: m.On(
createAccountFunc,
ctx,
mock.Anything,
mock.AnythingOfType("*accounts.Account"),
mock.AnythingOfType("[]accounts.PublicKey"),
),
DeployProject: m.On(
deployProjectFunc,
ctx,
mock.Anything,
mock.AnythingOfType("flowkit.UpdateContract"),
),
Expand All @@ -169,41 +157,35 @@ func DefaultMockServices() *MockServices {
),
GetBlock: m.On(
getBlockFunc,
ctx,
mock.Anything,
mock.AnythingOfType("flowkit.BlockQuery"),
),
GetTransactionByID: m.On(
getTransactionByIDFunc,
ctx,
mock.Anything,
mock.AnythingOfType("flow.Identifier"),
mock.AnythingOfType("bool"),
),
GetTransactionsByBlockID: m.On(
getTransactionsByBlockIDFunc,
ctx,
mock.Anything,
mock.AnythingOfType("flow.Identifier"),
),
RemoveContract: m.On(
removeContractFunc,
ctx,
mock.Anything,
mock.AnythingOfType("*accounts.Account"),
mock.AnythingOfType("string"),
),
SendTransaction: m.On(
sendTransactionFunc,
ctx,
mock.Anything,
mock.AnythingOfType("transactions.AccountRoles"),
mock.AnythingOfType("flowkit.Script"),
mock.AnythingOfType("uint64"),
),
SignTransactionPayload: m.On(
signTransactionPayloadFunc,
ctx,
mock.Anything,
mock.AnythingOfType("*accounts.Account"),
mock.AnythingOfType("[]uint8"),
Expand All @@ -220,7 +202,7 @@ func DefaultMockServices() *MockServices {
}

t.GetAccount.Run(func(args mock.Arguments) {
addr := args.Get(2).(flow.Address)
addr := args.Get(1).(flow.Address)
t.GetAccount.Return(tests.NewAccountWithAddress(addr.String()), nil)
})

Expand Down
3 changes: 3 additions & 0 deletions services.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,7 @@ type Services interface {
// SendTransaction will build and send a transaction to the Flow network, using the accounts provided for each role and
// contain the script. Transaction as well as transaction result will be returned in case the transaction is successfully submitted.
SendTransaction(context.Context, transactions.AccountRoles, Script, uint64) (*flow.Transaction, *flow.TransactionResult, error)

// ReplaceImportsInScript will replace the imports in the script code with the contracts from the network.
ReplaceImportsInScript(context.Context, Script) (Script, error)
}
46 changes: 46 additions & 0 deletions state.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"path/filepath"

"github.com/onflow/cadence/runtime"
"github.com/onflow/flow-go-sdk"
"github.com/onflow/flow-go-sdk/crypto"
"github.com/pkg/errors"
"golang.org/x/exp/slices"
Expand Down Expand Up @@ -226,6 +227,51 @@ func (p *State) AccountsForNetwork(network config.Network) *accounts.Accounts {
return &accs
}

// AccountByContractName returns the account for a contract by contract name.
func (p *State) AccountByContractName(contractName string, network config.Network) (*accounts.Account, error) {
deployments := p.conf.Deployments.ByNetwork(network.Name)
var accountName string
for _, d := range deployments {
for _, c := range d.Contracts {
if c.Name == contractName {
accountName = d.Account
break
}
}
}
if accountName == "" {
return nil, fmt.Errorf("deployment of %s not found for network %s", contractName, network.Name)
}

accs := p.Accounts()
if accs == nil {
return nil, fmt.Errorf("no accounts found in state")
}

var account *accounts.Account
for _, a := range *p.accounts {
if accountName == a.Name {
account = &a
break
}
}
if account == nil {
return nil, fmt.Errorf("account %s not found in state", accountName)
}

return account, nil
}

// ContractAddress returns the flow address for a contract given th network
func (p *State) ContractAddress(contract *config.Contract, network config.Network) (*flow.Address, error) {
acc, err := p.AccountByContractName(contract.Name, network)
if err != nil {
return nil, err
}

return &acc.Address, nil
}

// AliasesForNetwork returns all deployment aliases for a network.
func (p *State) AliasesForNetwork(network config.Network) project.LocationAliases {
aliases := make(project.LocationAliases)
Expand Down

0 comments on commit 8549eb0

Please sign in to comment.