Skip to content

Commit

Permalink
Merge branch 'release/v1.17.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
egieseke committed Jun 21, 2022
2 parents 7c7bab4 + 6b524e5 commit fae5b08
Show file tree
Hide file tree
Showing 26 changed files with 148 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ workflows:
name: 'test_go_<< matrix.go_version >>'
matrix:
parameters:
go_version: ['1.13', '1.14', '1.15', '1.16', '1.17']
go_version: ['1.15', '1.16', '1.17']

jobs:
test:
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# 1.17.0

## What's Changed
* Added GetMethodByName on Interface and Contract ([#330](https://github.com/algorand/go-algorand-sdk/pull/330))
* Regenerated code with the latest specification file (d012c9f5) ([#332](https://github.com/algorand/go-algorand-sdk/pull/332))
* Added helper method for formatting the algod API path ([#331](https://github.com/algorand/go-algorand-sdk/pull/331))
* Added method in ABI results object ([#329](https://github.com/algorand/go-algorand-sdk/pull/329))

# 1.16.0

## Important Note
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ test:

unit:
go test $(TEST_SOURCES_NO_CUCUMBER)
cd test && go test -timeout 0s --godog.strict=true --godog.format=pretty --godog.tags="@unit.offline,@unit.algod,@unit.indexer,@unit.transactions.keyreg,@unit.rekey,@unit.tealsign,@unit.dryrun,@unit.responses,@unit.applications,@unit.transactions,@unit.indexer.rekey,@unit.responses.messagepack,@unit.responses.231,@unit.responses.messagepack.231,@unit.responses.genesis,@unit.feetest,@unit.indexer.logs,@unit.abijson,@unit.transactions.payment,@unit.atomic_transaction_composer,@unit.responses.unlimited_assets,@unit.indexer.ledger_refactoring,@unit.algod.ledger_refactoring,@unit.dryrun.trace.application" --test.v .
cd test && go test -timeout 0s --godog.strict=true --godog.format=pretty --godog.tags="@unit.offline,@unit.algod,@unit.indexer,@unit.transactions.keyreg,@unit.rekey,@unit.tealsign,@unit.dryrun,@unit.responses,@unit.applications,@unit.transactions,@unit.indexer.rekey,@unit.responses.messagepack,@unit.responses.231,@unit.responses.messagepack.231,@unit.responses.genesis,@unit.feetest,@unit.indexer.logs,@unit.abijson,@unit.abijson.byname,@unit.transactions.payment,@unit.atomic_transaction_composer,@unit.responses.unlimited_assets,@unit.indexer.ledger_refactoring,@unit.algod.ledger_refactoring,@unit.dryrun.trace.application" --test.v .

integration:
go test $(TEST_SOURCES_NO_CUCUMBER)
Expand Down
32 changes: 32 additions & 0 deletions abi/interactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,30 @@ func (method *Method) GetTxCount() int {
return cnt
}

func GetMethodByName(methods []Method, name string) (Method, error) {
var filteredMethods []Method
for _, method := range methods {
if method.Name == name {
filteredMethods = append(filteredMethods, method)
}
}

if len(filteredMethods) > 1 {
var sigs []string
for _, method := range filteredMethods {
sigs = append(sigs, method.GetSignature())
}

return Method{}, fmt.Errorf("found %d methods with the same name %s", len(filteredMethods), strings.Join(sigs, ","))
}

if len(filteredMethods) == 0 {
return Method{}, fmt.Errorf("found 0 methods with the name %s", name)
}

return filteredMethods[0], nil
}

// Interface represents an ABI interface, which is a logically grouped
// collection of methods
type Interface struct {
Expand All @@ -285,6 +309,10 @@ type Interface struct {
Methods []Method `json:"methods"`
}

func (i *Interface) GetMethodByName(name string) (Method, error) {
return GetMethodByName(i.Methods, name)
}

// ContractNetworkInfo contains network-specific information about the contract
type ContractNetworkInfo struct {
// The application ID of the contract for this network
Expand All @@ -304,3 +332,7 @@ type Contract struct {
// The methods that the contract implements
Methods []Method `json:"methods"`
}

func (c *Contract) GetMethodByName(name string) (Method, error) {
return GetMethodByName(c.Methods, name)
}
2 changes: 1 addition & 1 deletion client/v2/algod/accountApplicationInformation.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ type AccountApplicationInformation struct {

// Do performs the HTTP request
func (s *AccountApplicationInformation) Do(ctx context.Context, headers ...*common.Header) (response models.AccountApplicationResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%v/applications/%v", s.address, s.applicationId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%s/applications/%s", common.EscapeParams(s.address, s.applicationId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/algod/accountAssetInformation.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ type AccountAssetInformation struct {

// Do performs the HTTP request
func (s *AccountAssetInformation) Do(ctx context.Context, headers ...*common.Header) (response models.AccountAssetResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%v/assets/%v", s.address, s.assetId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%s/assets/%s", common.EscapeParams(s.address, s.assetId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/algod/accountInformation.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ func (s *AccountInformation) Exclude(Exclude string) *AccountInformation {

// Do performs the HTTP request
func (s *AccountInformation) Do(ctx context.Context, headers ...*common.Header) (response models.Account, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%v", s.address), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%s", common.EscapeParams(s.address)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/algod/getApplicationByID.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ type GetApplicationByID struct {

// Do performs the HTTP request
func (s *GetApplicationByID) Do(ctx context.Context, headers ...*common.Header) (response models.Application, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/applications/%v", s.applicationId), nil, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/applications/%s", common.EscapeParams(s.applicationId)...), nil, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/algod/getAssetByID.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ type GetAssetByID struct {

// Do performs the HTTP request
func (s *GetAssetByID) Do(ctx context.Context, headers ...*common.Header) (response models.Asset, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/assets/%v", s.assetId), nil, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/assets/%s", common.EscapeParams(s.assetId)...), nil, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/algod/getProof.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ func (s *GetProof) Hashtype(Hashtype string) *GetProof {

// Do performs the HTTP request
func (s *GetProof) Do(ctx context.Context, headers ...*common.Header) (response models.ProofResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/blocks/%v/transactions/%v/proof", s.round, s.txid), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/blocks/%s/transactions/%s/proof", common.EscapeParams(s.round, s.txid)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/algod/waitForBlock.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ type StatusAfterBlock struct {

// Do performs the HTTP request
func (s *StatusAfterBlock) Do(ctx context.Context, headers ...*common.Header) (response models.NodeStatus, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/status/wait-for-block-after/%v", s.round), nil, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/status/wait-for-block-after/%s", common.EscapeParams(s.round)...), nil, headers)
return
}
16 changes: 16 additions & 0 deletions client/v2/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,19 @@ func (client *Client) GetRawMsgpack(ctx context.Context, response interface{}, p
func (client *Client) Post(ctx context.Context, response interface{}, path string, body interface{}, headers []*Header) error {
return client.submitForm(ctx, response, path, body, "POST", true /* encodeJSON */, headers)
}

// Helper function for correctly formatting and escaping URL path parameters.
// Used in the generated API client code.
func EscapeParams(params ...interface{}) []interface{} {
paramsStr := make([]interface{}, len(params))
for i, param := range params {
switch v := param.(type) {
case string:
paramsStr[i] = url.PathEscape(v)
default:
paramsStr[i] = fmt.Sprintf("%v", v)
}
}

return paramsStr
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupAccountAppLocalStates.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@ func (s *LookupAccountAppLocalStates) Next(Next string) *LookupAccountAppLocalSt

// Do performs the HTTP request
func (s *LookupAccountAppLocalStates) Do(ctx context.Context, headers ...*common.Header) (response models.ApplicationLocalStatesResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%v/apps-local-state", s.accountId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%s/apps-local-state", common.EscapeParams(s.accountId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupAccountAssets.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@ func (s *LookupAccountAssets) Next(Next string) *LookupAccountAssets {

// Do performs the HTTP request
func (s *LookupAccountAssets) Do(ctx context.Context, headers ...*common.Header) (response models.AssetHoldingsResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%v/assets", s.accountId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%s/assets", common.EscapeParams(s.accountId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupAccountCreatedApplications.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@ func (s *LookupAccountCreatedApplications) Next(Next string) *LookupAccountCreat

// Do performs the HTTP request
func (s *LookupAccountCreatedApplications) Do(ctx context.Context, headers ...*common.Header) (response models.ApplicationsResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%v/created-applications", s.accountId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%s/created-applications", common.EscapeParams(s.accountId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupAccountCreatedAssets.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@ func (s *LookupAccountCreatedAssets) Next(Next string) *LookupAccountCreatedAsse

// Do performs the HTTP request
func (s *LookupAccountCreatedAssets) Do(ctx context.Context, headers ...*common.Header) (response models.AssetsResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%v/created-assets", s.accountId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%s/created-assets", common.EscapeParams(s.accountId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupAccountTransactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,6 @@ func (s *LookupAccountTransactions) TXID(TXID string) *LookupAccountTransactions

// Do performs the HTTP request
func (s *LookupAccountTransactions) Do(ctx context.Context, headers ...*common.Header) (response models.TransactionsResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%v/transactions", s.accountId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/accounts/%s/transactions", common.EscapeParams(s.accountId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupApplicationByID.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ func (s *LookupApplicationByID) IncludeAll(IncludeAll bool) *LookupApplicationBy

// Do performs the HTTP request
func (s *LookupApplicationByID) Do(ctx context.Context, headers ...*common.Header) (response models.ApplicationResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/applications/%v", s.applicationId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/applications/%s", common.EscapeParams(s.applicationId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupApplicationLogsByID.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,6 @@ func (s *LookupApplicationLogsByID) Txid(Txid string) *LookupApplicationLogsByID

// Do performs the HTTP request
func (s *LookupApplicationLogsByID) Do(ctx context.Context, headers ...*common.Header) (response models.ApplicationLogsResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/applications/%v/logs", s.applicationId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/applications/%s/logs", common.EscapeParams(s.applicationId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupAssetBalances.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,6 @@ func (s *LookupAssetBalances) NextToken(NextToken string) *LookupAssetBalances {

// Do performs the HTTP request
func (s *LookupAssetBalances) Do(ctx context.Context, headers ...*common.Header) (response models.AssetBalancesResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/assets/%v/balances", s.assetId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/assets/%s/balances", common.EscapeParams(s.assetId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupAssetTransactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,6 @@ func (s *LookupAssetTransactions) TXID(TXID string) *LookupAssetTransactions {

// Do performs the HTTP request
func (s *LookupAssetTransactions) Do(ctx context.Context, headers ...*common.Header) (response models.TransactionsResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/assets/%v/transactions", s.assetId), s.p, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/assets/%s/transactions", common.EscapeParams(s.assetId)...), s.p, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupBlock.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ type LookupBlock struct {

// Do performs the HTTP request
func (s *LookupBlock) Do(ctx context.Context, headers ...*common.Header) (response models.Block, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/blocks/%v", s.roundNumber), nil, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/blocks/%s", common.EscapeParams(s.roundNumber)...), nil, headers)
return
}
2 changes: 1 addition & 1 deletion client/v2/indexer/lookupTransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ type LookupTransaction struct {

// Do performs the HTTP request
func (s *LookupTransaction) Do(ctx context.Context, headers ...*common.Header) (response models.TransactionResponse, err error) {
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/transactions/%v", s.txid), nil, headers)
err = s.c.get(ctx, &response, fmt.Sprintf("/v2/transactions/%s", common.EscapeParams(s.txid)...), nil, headers)
return
}
4 changes: 3 additions & 1 deletion future/atomicTransactionComposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type ABIMethodResult struct {
TxID string
// Information about the confirmed transaction that invoked the ABI method call.
TransactionInfo models.PendingTransactionInfoResponse
// Method that was called for this ABIMethodResult
Method abi.Method
// The raw bytes of the return value from the ABI method call. This will be empty if the method
// does not return a value (return type "void").
RawReturnValue []byte
Expand Down Expand Up @@ -628,7 +630,7 @@ func (atc *AtomicTransactionComposer) Execute(client *algod.Client, ctx context.
continue
}

result := ABIMethodResult{TxID: txContext.txID()}
result := ABIMethodResult{TxID: txContext.txID(), Method: *txContext.method}

if i == indexToWaitFor {
result.TransactionInfo = groupInfo
Expand Down
6 changes: 1 addition & 5 deletions test/applications_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,18 +596,14 @@ func theAppShouldHaveReturned(commaSeparatedB64Results string) error {
return fmt.Errorf("length of expected results doesn't match actual: %d != %d", len(b64ExpectedResults), len(txComposerResult.MethodResults))
}

if len(txComposerMethods) != len(txComposerResult.MethodResults) {
return fmt.Errorf("length of composer's methods doesn't match results: %d != %d", len(txComposerMethods), len(txComposerResult.MethodResults))
}

for i, b64ExpectedResult := range b64ExpectedResults {
expectedResult, err := base64.StdEncoding.DecodeString(b64ExpectedResult)
if err != nil {
return err
}

actualResult := txComposerResult.MethodResults[i]
method := txComposerMethods[i]
method := actualResult.Method

if actualResult.DecodeError != nil {
return actualResult.DecodeError
Expand Down
71 changes: 68 additions & 3 deletions test/steps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ var groupTxnBytes []byte
var data []byte
var sig types.Signature
var abiMethod abi.Method
var abiMethods []abi.Method
var abiJsonString string
var abiInterface abi.Interface
var abiContract abi.Contract
var txComposer future.AtomicTransactionComposer
var txComposerMethods []abi.Method
var accountTxSigner future.BasicAccountTransactionSigner
var methodArgs []interface{}
var sigTxs [][]byte
Expand Down Expand Up @@ -323,9 +323,16 @@ func FeatureContext(s *godog.Suite) {
s.Step(`^the decoded transaction should equal the original$`, theDecodedTransactionShouldEqualTheOriginal)
s.Step(`^a dryrun response file "([^"]*)" and a transaction at index "([^"]*)"$`, aDryrunResponseFileAndATransactionAtIndex)
s.Step(`^calling app trace produces "([^"]*)"$`, callingAppTraceProduces)
s.Step(`^I append to my Method objects list in the case of a non-empty signature "([^"]*)"$`, iAppendToMyMethodObjectsListInTheCaseOfANonemptySignature)
s.Step(`^I create an Interface object from my Method objects list$`, iCreateAnInterfaceObjectFromMyMethodObjectsList)
s.Step(`^I create a Contract object from my Method objects list$`, iCreateAContractObjectFromMyMethodObjectsList)
s.Step(`^I get the method from the Interface by name "([^"]*)"$`, iGetTheMethodFromTheInterfaceByName)
s.Step(`^I get the method from the Contract by name "([^"]*)"$`, iGetTheMethodFromTheContractByName)
s.Step(`^the produced method signature should equal "([^"]*)"\. If there is an error it begins with "([^"]*)"$`, theProducedMethodSignatureShouldEqualIfThereIsAnErrorItBeginsWith)

s.BeforeScenario(func(interface{}) {
stxObj = types.SignedTxn{}
abiMethods = nil
kcl.RenewWalletHandle(handle)
})
}
Expand Down Expand Up @@ -2061,6 +2068,66 @@ func serializeContractObjectIntoJson() error {
return nil
}

func iAppendToMyMethodObjectsListInTheCaseOfANonemptySignature(arg1 string) error {
if arg1 == "" {
return nil
}

meth, err := abi.MethodFromSignature(arg1)
abiMethods = append(abiMethods, meth)
return err
}

func iCreateAnInterfaceObjectFromMyMethodObjectsList() error {
abiInterface = abi.Interface{
Name: "",
Methods: abiMethods,
}
return nil
}

func iGetTheMethodFromTheInterfaceByName(arg1 string) error {
abiMethod, globalErrForExamination = abiInterface.GetMethodByName(arg1)
return nil
}

func iCreateAContractObjectFromMyMethodObjectsList() error {
abiContract = abi.Contract{
Name: "",
Methods: abiMethods,
}
return nil
}

func iGetTheMethodFromTheContractByName(arg1 string) error {
abiMethod, globalErrForExamination = abiContract.GetMethodByName(arg1)
return nil
}

func theProducedMethodSignatureShouldEqualIfThereIsAnErrorItBeginsWith(arg1, arg2 string) error {
if abiMethod.Name != "" {
if arg2 != "" {
return fmt.Errorf("expected error condition but got a method")
}
if arg1 != abiMethod.GetSignature() {
return fmt.Errorf("signature mismatch: %s != %s", arg1, abiMethod.GetSignature())
}
} else if globalErrForExamination != nil {
if arg2 == "" {
return fmt.Errorf("got error %s, expected no error", globalErrForExamination)
}

if !strings.Contains(globalErrForExamination.Error(), arg2) {
return fmt.Errorf("produced error does not match expected: %q does not contain %q", globalErrForExamination.Error(), arg2)
}

} else {
return fmt.Errorf("both abi method and error string are empty")
}

return nil
}

// equality helper methods
func checkEqualMethods(method1, method2 abi.Method) bool {
if method1.Name != method2.Name || method1.Desc != method2.Desc {
Expand Down Expand Up @@ -2168,7 +2235,6 @@ func deserializeContractJson() error {

func aNewAtomicTransactionComposer() error {
txComposer = future.AtomicTransactionComposer{}
txComposerMethods = nil
return nil
}

Expand Down Expand Up @@ -2401,7 +2467,6 @@ func addMethodCallHelper(accountType, strOnComplete, approvalProgram, clearProgr
methodCallParams.Note = note
}

txComposerMethods = append(txComposerMethods, abiMethod)
return txComposer.AddMethodCall(methodCallParams)
}

Expand Down

0 comments on commit fae5b08

Please sign in to comment.