Skip to content

Commit

Permalink
Merge branch 'master' into update/emulator
Browse files Browse the repository at this point in the history
  • Loading branch information
sideninja authored Nov 9, 2021
2 parents e3f22e4 + e9359d3 commit 8ed61dd
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 13 deletions.
6 changes: 5 additions & 1 deletion pkg/flowkit/services/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ func (t *Transactions) Build(
tx := flowkit.NewTransaction().
SetPayer(payer).
SetProposer(proposerAccount, proposerKeyIndex).
AddAuthorizers(authorizers).
SetGasLimit(gasLimit).
SetBlockReference(latestBlock)

Expand Down Expand Up @@ -139,6 +138,11 @@ func (t *Transactions) Build(
return nil, err
}

tx, err = tx.AddAuthorizers(authorizers)
if err != nil {
return nil, err
}

return tx, nil
}

Expand Down
179 changes: 179 additions & 0 deletions pkg/flowkit/services/transactions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,183 @@ func TestTransactions_Integration(t *testing.T) {
)
})

t.Run("Sign transaction", func(t *testing.T) {
t.Parallel()
state, s := setupIntegration()
setupAccounts(state, s)

a, _ := state.Accounts().ByName("Alice")

tx, err := s.Transactions.Build(
a.Address(),
nil,
a.Address(),
0,
tests.TransactionSimple.Source,
tests.TransactionSimple.Filename,
1000,
nil,
"",
)

assert.Nil(t, err)
assert.NotNil(t, tx)

txSigned, err := s.Transactions.Sign(
a,
[]byte(fmt.Sprintf("%x", tx.FlowTransaction().Encode())),
true,
)
assert.Nil(t, err)
assert.NotNil(t, txSigned)
assert.Equal(t, len(txSigned.FlowTransaction().Authorizers), 0)
assert.Equal(t, txSigned.FlowTransaction().Payer, a.Address())
assert.Equal(t, txSigned.FlowTransaction().ProposalKey.Address, a.Address())
assert.Equal(t, txSigned.FlowTransaction().ProposalKey.KeyIndex, 0)
assert.Equal(t, txSigned.FlowTransaction().Script, tests.TransactionSimple.Source)
})

t.Run("Build, Sign and Send Transaction", func(t *testing.T) {
t.Parallel()
state, s := setupIntegration()
setupAccounts(state, s)

a, _ := state.Accounts().ByName("Alice")

tx, err := s.Transactions.Build(
a.Address(),
[]flow.Address{a.Address()},
a.Address(),
0,
tests.TransactionSingleAuth.Source,
tests.TransactionSingleAuth.Filename,
1000,
nil,
"",
)

assert.Nil(t, err)
assert.NotNil(t, tx)

txSigned, err := s.Transactions.Sign(
a,
[]byte(fmt.Sprintf("%x", tx.FlowTransaction().Encode())),
true,
)
assert.Nil(t, err)
assert.NotNil(t, txSigned)

txSent, txResult, err := s.Transactions.SendSigned(
[]byte(fmt.Sprintf("%x", txSigned.FlowTransaction().Encode())),
)
assert.Nil(t, err)
assert.Equal(t, txResult.Status, flow.TransactionStatusSealed)
assert.NotNil(t, txSent.ID())

})

t.Run("Fails signing transaction, wrong account", func(t *testing.T) {
t.Parallel()
state, s := setupIntegration()
setupAccounts(state, s)

a, _ := state.Accounts().ByName("Alice")

tx, err := s.Transactions.Build(
a.Address(),
[]flow.Address{a.Address()},
a.Address(),
0,
tests.TransactionSingleAuth.Source,
tests.TransactionSingleAuth.Filename,
1000,
nil,
"",
)

assert.Nil(t, err)
assert.NotNil(t, tx)

// sign with wrong account
a, _ = state.Accounts().ByName("Bob")

txSigned, err := s.Transactions.Sign(
a,
[]byte(fmt.Sprintf("%x", tx.FlowTransaction().Encode())),
true,
)
assert.EqualError(t, err, "not a valid signer 179b6b1cb6755e31, proposer: 01cf0e2f2f715450, payer: 01cf0e2f2f715450, authorizers: [01cf0e2f2f715450]")
assert.Nil(t, txSigned)
})

t.Run("Fails building, authorizers mismatch", func(t *testing.T) {
t.Parallel()
state, s := setupIntegration()
setupAccounts(state, s)

a, _ := state.Accounts().ByName("Alice")

tx, err := s.Transactions.Build(
a.Address(),
[]flow.Address{a.Address()},
a.Address(),
0,
tests.TransactionTwoAuth.Source,
tests.TransactionTwoAuth.Filename,
1000,
nil,
"",
)

assert.EqualError(t, err, "provided authorizers length mismatch, required authorizers 2, but provided 1")
assert.Nil(t, tx)
})

t.Run("Send Transaction", func(t *testing.T) {
t.Parallel()
state, s := setupIntegration()
setupAccounts(state, s)

a, _ := state.Accounts().ByName("Alice")

tx, txr, err := s.Transactions.Send(
a,
tests.TransactionSingleAuth.Source,
tests.TransactionSingleAuth.Filename,
1000,
nil,
"",
)
assert.NoError(t, err)
assert.Equal(t, tx.Payer.String(), a.Address().String())
assert.Equal(t, tx.ProposalKey.KeyIndex, a.Key().Index())
assert.Nil(t, txr.Error)
assert.Equal(t, txr.Status, flow.TransactionStatusSealed)
})

t.Run("Send Transaction with arguments", func(t *testing.T) {
t.Parallel()
state, s := setupIntegration()
setupAccounts(state, s)

a, _ := state.Accounts().ByName("Alice")
args := []cadence.Value{
cadence.String("Bar"),
}

tx, txr, err := s.Transactions.Send(
a,
tests.TransactionArgString.Source,
tests.TransactionArgString.Filename,
1000,
args,
"",
)
assert.NoError(t, err)
assert.Equal(t, tx.Payer.String(), a.Address().String())
assert.Equal(t, tx.ProposalKey.KeyIndex, a.Key().Index())
assert.Equal(t, fmt.Sprintf("%x", tx.Arguments), "[7b2274797065223a22537472696e67222c2276616c7565223a22426172227d0a]")
assert.Nil(t, txr.Error)
assert.Equal(t, txr.Status, flow.TransactionStatusSealed)
})
}
71 changes: 59 additions & 12 deletions pkg/flowkit/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import (
"encoding/hex"
"fmt"

"github.com/onflow/cadence/runtime/cmd"
"github.com/onflow/cadence/runtime/common"

jsoncdc "github.com/onflow/cadence/encoding/json"

"github.com/onflow/flow-go-sdk/templates"
Expand Down Expand Up @@ -105,15 +108,8 @@ func addAccountContractWithArgs(
}
}`

cadenceName, err := cadence.NewString(contract.Name)
if err != nil {
return nil, err
}

cadenceCode, err := cadence.NewString(contract.SourceHex())
if err != nil {
return nil, err
}
cadenceName := cadence.String(contract.Name)
cadenceCode := cadence.String(contract.SourceHex())

tx := flow.NewTransaction().
AddRawArgument(jsoncdc.MustEncode(cadenceName)).
Expand All @@ -136,7 +132,7 @@ func addAccountContractWithArgs(
tx.SetGasLimit(maxGasLimit)

t := &Transaction{tx: tx}
err = t.SetSigner(signer)
err := t.SetSigner(signer)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -205,10 +201,38 @@ func (t *Transaction) SetSigner(account *Account) error {
return err
}

if !t.validSigner(account.Address()) {
return fmt.Errorf(
"not a valid signer %s, proposer: %s, payer: %s, authorizers: %s",
account.Address(),
t.tx.ProposalKey.Address,
t.tx.Payer,
t.tx.Authorizers,
)
}

t.signer = account
return nil
}

// validSigner checks whether the signer is valid for transaction
func (t *Transaction) validSigner(s flow.Address) bool {
return t.tx.ProposalKey.Address == s ||
t.tx.Payer == s ||
t.authorizersContains(s)
}

// authorizersContains checks whether address is in the authorizer list
func (t *Transaction) authorizersContains(address flow.Address) bool {
for _, a := range t.tx.Authorizers {
if address == a {
return true
}
}

return false
}

// SetProposer sets the proposer for transaction.
func (t *Transaction) SetProposer(proposer *flow.Account, keyIndex int) *Transaction {
t.proposer = proposer
Expand Down Expand Up @@ -259,12 +283,35 @@ func (t *Transaction) AddArgument(arg cadence.Value) error {
}

// AddAuthorizers add group of authorizers.
func (t *Transaction) AddAuthorizers(authorizers []flow.Address) *Transaction {
func (t *Transaction) AddAuthorizers(authorizers []flow.Address) (*Transaction, error) {
program, _ := cmd.PrepareProgram(
string(t.tx.Script),
common.StringLocation(""),
map[common.LocationID]string{},
)

// get authorizers param list if exists
if program.SoleTransactionDeclaration().Prepare != nil {
requiredAuths := program.SoleTransactionDeclaration().
Prepare.
FunctionDeclaration.
ParameterList.
Parameters

if len(requiredAuths) != len(authorizers) {
return nil, fmt.Errorf(
"provided authorizers length mismatch, required authorizers %d, but provided %d",
len(requiredAuths),
len(authorizers),
)
}
}

for _, authorizer := range authorizers {
t.tx.AddAuthorizer(authorizer)
}

return t
return t, nil
}

// Sign signs transaction using signer account.
Expand Down
18 changes: 18 additions & 0 deletions tests/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,24 @@ var TransactionSimple = resource{
`),
}

var TransactionSingleAuth = resource{
Filename: "transactionAuth1.cdc",
Source: []byte(`
transaction() {
prepare(authorizer: AuthAccount) {}
}
`),
}

var TransactionTwoAuth = resource{
Filename: "transactionAuth2.cdc",
Source: []byte(`
transaction() {
prepare(auth1: AuthAccount, auth2: AuthAccount) {}
}
`),
}

var ScriptWithError = resource{
Filename: "scriptError.cdc",
Source: []byte(`
Expand Down

0 comments on commit 8ed61dd

Please sign in to comment.