Skip to content

Commit 74b4ae8

Browse files
authored
Merge pull request #83 from kaleido-io/add-erc20
adding support for erc20 test case
2 parents 2c9c793 + 57a91a3 commit 74b4ae8

File tree

4 files changed

+373
-42
lines changed

4 files changed

+373
-42
lines changed

internal/conf/conf.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,6 @@ type InstanceConfig struct {
9292
SubscriptionCoreOptions *core.SubscriptionCoreOptions `json:"subscriptionOptions,omitempty" yaml:"subscriptionOptions,omitempty"`
9393
}
9494

95-
type SubscriptionOptions struct {
96-
}
97-
9895
type TestCaseConfig struct {
9996
Name fftypes.FFEnum `json:"name" yaml:"name"`
10097
Workers int `json:"workers" yaml:"workers"`
@@ -189,6 +186,8 @@ var (
189186
PerfTestTokenMint fftypes.FFEnum = "token_mint"
190187
// PerfTestCustomEthereumContract invokes a custom smart contract and checks events emitted by it
191188
PerfTestCustomEthereumContract fftypes.FFEnum = "custom_ethereum_contract"
189+
// PerfTestCustomEthereumContract invokes an erc20 transfer and checks events emitted by it
190+
PerfTestERC20TransferContract fftypes.FFEnum = "erc20_transfer"
192191
// PerfTestCustomFabricContract invokes a custom smart contract and checks events emitted by it
193192
PerfTestCustomFabricContract fftypes.FFEnum = "custom_fabric_contract"
194193
// PerfTestBlobBroadcast broadcasts a blob

internal/perf/erc20transfer.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// Copyright © 2024 Kaleido, Inc.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
package perf
18+
19+
import (
20+
"encoding/json"
21+
"fmt"
22+
"net/url"
23+
24+
"github.com/hyperledger/firefly-perf-cli/internal/conf"
25+
log "github.com/sirupsen/logrus"
26+
27+
"github.com/hyperledger/firefly-common/pkg/fftypes"
28+
)
29+
30+
type erc20Transfer struct {
31+
testBase
32+
}
33+
34+
func newERC20TransferTestWorker(pr *perfRunner, workerID int, actionsPerLoop int) TestCase {
35+
return &erc20Transfer{
36+
testBase: testBase{
37+
pr: pr,
38+
workerID: workerID,
39+
actionsPerLoop: actionsPerLoop,
40+
},
41+
}
42+
}
43+
44+
func (tc *erc20Transfer) Name() string {
45+
return conf.PerfTestERC20TransferContract.String()
46+
}
47+
48+
func (tc *erc20Transfer) IDType() TrackingIDType {
49+
return TrackingIDTypeWorkerNumber
50+
}
51+
52+
func (tc *erc20Transfer) RunOnce(iterationCount int) (string, error) {
53+
idempotencyKey := tc.pr.getIdempotencyKey(tc.workerID, iterationCount)
54+
invokeOptionsJSON := ""
55+
if tc.pr.cfg.InvokeOptions != nil {
56+
b, err := json.Marshal(tc.pr.cfg.InvokeOptions)
57+
if err == nil {
58+
invokeOptionsJSON = fmt.Sprintf(",\n \"options\": %s", b)
59+
}
60+
}
61+
payload := fmt.Sprintf(`{
62+
"location": {
63+
"address": "%s"
64+
},
65+
"method": {
66+
"name": "transfer",
67+
"params": [
68+
{
69+
"name": "to",
70+
"schema": {
71+
"type": "string",
72+
"details": {
73+
"type": "address"
74+
}
75+
}
76+
},
77+
{
78+
"name": "amount",
79+
"schema": {
80+
"type": "integer",
81+
"details": {
82+
"type": "uint256"
83+
}
84+
}
85+
}
86+
],
87+
"returns": [
88+
{
89+
"name": "",
90+
"schema": {
91+
"type": "boolean",
92+
"details": {
93+
"type": "bool"
94+
}
95+
}
96+
}
97+
]
98+
},
99+
"input": {
100+
"to": "0x2989c0f1f7b9e861f521dbfc4069b74ab0ce12a2",
101+
"amount": 1
102+
},
103+
"key": "%s",
104+
"idempotencyKey": "%s"%s
105+
}`, tc.pr.cfg.ContractOptions.Address, tc.pr.cfg.SigningKey, idempotencyKey, invokeOptionsJSON)
106+
var resContractCall map[string]interface{}
107+
var resError fftypes.RESTError
108+
fullPath, err := url.JoinPath(tc.pr.client.BaseURL, tc.pr.cfg.FFNamespacePath, "contracts/invoke")
109+
if err != nil {
110+
return "", err
111+
}
112+
res, err := tc.pr.client.R().
113+
SetHeaders(map[string]string{
114+
"Accept": "application/json",
115+
"Content-Type": "application/json",
116+
}).
117+
SetBody([]byte(payload)).
118+
SetResult(&resContractCall).
119+
SetError(&resError).
120+
Post(fullPath)
121+
id := resContractCall["id"].(string)
122+
if err != nil || res.IsError() {
123+
if res.StatusCode() == 409 {
124+
log.Warnf("Request already received by FireFly: %+v", &resError)
125+
} else {
126+
return "", fmt.Errorf("Error invoking contract [%d]: %s (%+v)", resStatus(res), err, &resError)
127+
}
128+
}
129+
log.Infof("Submitted token transfer: %s", id)
130+
131+
return id, nil
132+
}

0 commit comments

Comments
 (0)