From d1edd9ed06d2db9dab33ea66b8f43ec9944f5f19 Mon Sep 17 00:00:00 2001 From: cfal Date: Tue, 18 Jul 2023 02:18:54 +0800 Subject: [PATCH 01/14] packages-ts/gauntlet-cosmos-contracts: remove hardcoded cw20_base local code id --- .../src/commands/contracts/link/deploy.ts | 4 +++- packages-ts/gauntlet-cosmos-contracts/src/lib/constants.ts | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/link/deploy.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/link/deploy.ts index 50c84a70..3cd43b75 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/link/deploy.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/link/deploy.ts @@ -25,7 +25,9 @@ export default class DeployLink extends CosmosCommand { execute = async () => { await prompt(`Begin deploying LINK Token?`) - const deploy = await this.deploy(CW20_BASE_CODE_IDs[this.flags.network], { + const codeId = this.codeIds['cw20_base'] || CW20_BASE_CODE_IDs[this.flags.network]; + logger.info('Using code ID: ' + codeId); + const deploy = await this.deploy(codeId, { name: 'ChainLink Token', symbol: 'LINK', decimals: TOKEN_DECIMALS, diff --git a/packages-ts/gauntlet-cosmos-contracts/src/lib/constants.ts b/packages-ts/gauntlet-cosmos-contracts/src/lib/constants.ts index 95f82873..fed4ab50 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/lib/constants.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/lib/constants.ts @@ -21,7 +21,6 @@ export const ORACLES_MAX_LENGTH = 31 export const CW20_BASE_CODE_IDs = { mainnet: 3, - local: 32, 'testnet-bombay': 148, 'testnet-bombay-internal': 148, } From 6175e58d70294f49a4bdea18c69f147ca87229bf Mon Sep 17 00:00:00 2001 From: cfal Date: Wed, 12 Jul 2023 16:22:22 +0800 Subject: [PATCH 02/14] initial test changes, upload cw20_base before token deploy --- integration-tests/common/common.go | 2 +- integration-tests/common/gauntlet_common.go | 138 ++++++++++++++++++++ integration-tests/smoke/ocr2_test.go | 26 +++- ops/gauntlet/gauntlet_cosmos.go | 93 +++++++------ 4 files changed, 214 insertions(+), 45 deletions(-) create mode 100644 integration-tests/common/gauntlet_common.go diff --git a/integration-tests/common/common.go b/integration-tests/common/common.go index 3b808569..c4b2911e 100644 --- a/integration-tests/common/common.go +++ b/integration-tests/common/common.go @@ -33,7 +33,7 @@ type Common struct { NodeCount int TTL time.Duration Testnet bool - L2RPCUrl string + RPCUrl string PrivateKey string Account string ClConfig map[string]any diff --git a/integration-tests/common/gauntlet_common.go b/integration-tests/common/gauntlet_common.go new file mode 100644 index 00000000..0505e2d0 --- /dev/null +++ b/integration-tests/common/gauntlet_common.go @@ -0,0 +1,138 @@ +package common + +import ( + "encoding/json" + "errors" + "fmt" + "os" + + "github.com/smartcontractkit/chainlink-starknet/integration-tests/utils" +) + +var ( + ethAddressGoerli = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" + nAccount string +) + +func (testState *Test) fundNodes() ([]string, error) { + l := utils.GetTestLogger(testState.T) + var nAccounts []string + var err error + for _, key := range testState.GetNodeKeys() { + if key.TXKey.Data.Attributes.StarkKey == "" { + return nil, errors.New("stark key can't be empty") + } + nAccount, err = testState.Cg.DeployAccountContract(100, key.TXKey.Data.Attributes.StarkKey) + if err != nil { + return nil, err + } + nAccounts = append(nAccounts, nAccount) + } + + if err != nil { + return nil, err + } + + for _, key := range nAccounts { + // We are not deploying in parallel here due to testnet limitations (429 too many requests) + l.Debug().Msg(fmt.Sprintf("Funding node with address: %s", key)) + _, err = testState.Cg.TransferToken(ethAddressGoerli, key, "100000000000000000") // Transferring 1 ETH to each node + if err != nil { + return nil, err + } + } + + return nAccounts, nil +} + +func (testState *Test) deployLinkToken() error { + _, err := testState.Cg.UploadContract("cw20_base") + if err != nil { + return err + } + + testState.LinkTokenAddr, err = testState.Cg.DeployLinkTokenContract() + if err != nil { + return err + } + err = os.Setenv("LINK", testState.LinkTokenAddr) + if err != nil { + return err + } + return nil +} + +func (testState *Test) deployAccessController() error { + var err error + testState.AccessControllerAddr, err = testState.Cg.DeployAccessControllerContract() + if err != nil { + return err + } + err = os.Setenv("BILLING_ACCESS_CONTROLLER", testState.AccessControllerAddr) + if err != nil { + return err + } + return nil +} + +func (testState *Test) setConfigDetails(ocrAddress string) error { + cfg, err := testState.LoadOCR2Config() + if err != nil { + return err + } + var parsedConfig []byte + parsedConfig, err = json.Marshal(cfg) + if err != nil { + return err + } + _, err = testState.Cg.SetConfigDetails(string(parsedConfig), ocrAddress) + return err +} + +func (testState *Test) DeployGauntlet(minSubmissionValue int64, maxSubmissionValue int64, decimals int, name string, observationPaymentGjuels int64, transmissionPaymentGjuels int64) error { + err := testState.Cg.InstallDependencies() + if err != nil { + return err + } + + testState.AccountAddresses, err = testState.fundNodes() + if err != nil { + return err + } + + err = testState.deployLinkToken() + if err != nil { + return err + } + + err = testState.deployAccessController() + if err != nil { + return err + } + + testState.OCRAddr, err = testState.Cg.DeployOCR2ControllerContract(minSubmissionValue, maxSubmissionValue, decimals, name, testState.LinkTokenAddr) + if err != nil { + return err + } + + testState.ProxyAddr, err = testState.Cg.DeployOCR2ProxyContract(testState.OCRAddr) + if err != nil { + return err + } + _, err = testState.Cg.AddAccess(testState.OCRAddr, testState.ProxyAddr) + if err != nil { + return err + } + + _, err = testState.Cg.MintLinkToken(testState.LinkTokenAddr, testState.OCRAddr, "100000000000000000000") + if err != nil { + return err + } + _, err = testState.Cg.SetOCRBilling(observationPaymentGjuels, transmissionPaymentGjuels, testState.OCRAddr) + if err != nil { + return err + } + + err = testState.setConfigDetails(testState.OCRAddr) + return err +} diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 1c94bf21..7262aecf 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -14,11 +14,14 @@ import ( ) var ( - err error + err error + testState *common.Test + decimals = 9 + mockServerVal = 900000000 ) func TestOCRBasic(t *testing.T) { - testState := &common.Test{ + testState = &common.Test{ T: t, } testState.Common = common.New() @@ -31,6 +34,21 @@ func TestOCRBasic(t *testing.T) { if testState.Common.Env.WillUseRemoteRunner() { return // short circuit here if using a remote runner } - err = actions.TeardownSuite(testState.T, testState.Common.Env, "./", nil, nil, zapcore.DPanicLevel, nil) - require.NoError(testState.T, err) + err = testState.Cg.SetupNetwork(testState.Common.RPCUrl) + require.NoError(t, err, "Setting up gauntlet network should not fail") + err = testState.DeployGauntlet(0, 100000000000, decimals, "auto", 1, 1) + require.NoError(t, err, "Deploying contracts should not fail") + if !testState.Common.Testnet { + testState.Devnet.AutoLoadState(testState.OCR2Client, testState.OCRAddr) + } + testState.SetUpNodes(mockServerVal) + + err = testState.ValidateRounds(10, false) + require.NoError(t, err, "Validating round should not fail") + + t.Cleanup(func() { + err = actions.TeardownSuite(testState.T, testState.Common.Env, "./", nil, nil, zapcore.DPanicLevel, nil) + // err = actions.TeardownSuite(t, testState.Common.Env, utils.ProjectRoot, testState.Cc.ChainlinkNodes, nil, zapcore.ErrorLevel) + require.NoError(t, err, "Error tearing down environment") + }) } diff --git a/ops/gauntlet/gauntlet_cosmos.go b/ops/gauntlet/gauntlet_cosmos.go index 6d87dff2..3a520025 100644 --- a/ops/gauntlet/gauntlet_cosmos.go +++ b/ops/gauntlet/gauntlet_cosmos.go @@ -25,6 +25,7 @@ type GauntletResponse struct { Hash string `json:"hash"` Address string `json:"address"` Status string `json:"status"` + CodeId int `json:"codeId"` Tx struct { Address string `json:"address"` @@ -70,26 +71,38 @@ func (cg *CosmosGauntlet) FetchGauntletJsonOutput() (*GauntletResponse, error) { return payload, nil } -// // SetupNetwork Sets up a new network and sets the NODE_URL for Devnet / Cosmos RPC -// func (sg *CosmosGauntlet) SetupNetwork(addr string) error { -// sg.G.AddNetworkConfigVar("NODE_URL", addr) -// err := sg.G.WriteNetworkConfigMap(sg.dir + "packages-ts/cosmos-gauntlet-cli/networks/") -// if err != nil { -// return err -// } +// SetupNetwork Sets up a new network and sets the NODE_URL for Devnet / Cosmos RPC +func (sg *CosmosGauntlet) SetupNetwork(addr string) error { + sg.G.AddNetworkConfigVar("NODE_URL", addr) + err := sg.G.WriteNetworkConfigMap(sg.dir + "packages-ts/gauntlet-cosmos-contracts/networks/") + if err != nil { + return err + } -// return nil -// } + return nil +} -// func (sg *CosmosGauntlet) InstallDependencies() error { -// sg.G.Command = "yarn" -// _, err := sg.G.ExecCommand([]string{"install"}, *sg.options) -// if err != nil { -// return err -// } -// sg.G.Command = "gauntlet" -// return nil -// } +func (sg *CosmosGauntlet) InstallDependencies() error { + sg.G.Command = "yarn" + _, err := sg.G.ExecCommand([]string{"install"}, *sg.options) + if err != nil { + return err + } + sg.G.Command = "gauntlet" + return nil +} + +func (sg *CosmosGauntlet) UploadContract(name string) (int, error) { + _, err := sg.G.ExecCommand([]string{"upload", name}, *sg.options) + if err != nil { + return 0, err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return 0, err + } + return sg.gr.Responses[0].Tx.CodeId, nil +} // func (sg *CosmosGauntlet) DeployAccountContract(salt int64, pubKey string) (string, error) { // _, err := sg.G.ExecCommand([]string{"account:deploy", fmt.Sprintf("--salt=%d", salt), fmt.Sprintf("--publicKey=%s", pubKey)}, *sg.options) @@ -103,17 +116,17 @@ func (cg *CosmosGauntlet) FetchGauntletJsonOutput() (*GauntletResponse, error) { // return sg.gr.Responses[0].Contract, nil // } -// func (sg *CosmosGauntlet) DeployLinkTokenContract() (string, error) { -// _, err := sg.G.ExecCommand([]string{"ERC20:deploy", "--link"}, *sg.options) -// if err != nil { -// return "", err -// } -// sg.gr, err = sg.FetchGauntletJsonOutput() -// if err != nil { -// return "", err -// } -// return sg.gr.Responses[0].Contract, nil -// } +func (sg *CosmosGauntlet) DeployLinkTokenContract() (string, error) { + _, err := sg.G.ExecCommand([]string{"token:deploy"}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} // func (sg *CosmosGauntlet) MintLinkToken(token, to, amount string) (string, error) { // _, err := sg.G.ExecCommand([]string{"ERC20:mint", fmt.Sprintf("--account=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *sg.options) @@ -127,17 +140,17 @@ func (cg *CosmosGauntlet) FetchGauntletJsonOutput() (*GauntletResponse, error) { // return sg.gr.Responses[0].Contract, nil // } -// func (sg *CosmosGauntlet) TransferToken(token, to, amount string) (string, error) { -// _, err := sg.G.ExecCommand([]string{"ERC20:transfer", fmt.Sprintf("--recipient=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *sg.options) -// if err != nil { -// return "", err -// } -// sg.gr, err = sg.FetchGauntletJsonOutput() -// if err != nil { -// return "", err -// } -// return sg.gr.Responses[0].Contract, nil -// } +func (sg *CosmosGauntlet) TransferToken(token, to, amount string) (string, error) { + _, err := sg.G.ExecCommand([]string{"ERC20:transfer", fmt.Sprintf("--recipient=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *sg.options) + if err != nil { + return "", err + } + sg.gr, err = sg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return sg.gr.Responses[0].Contract, nil +} // func (sg *CosmosGauntlet) DeployOCR2ControllerContract(minSubmissionValue int64, maxSubmissionValue int64, decimals int, name string, linkTokenAddress string) (string, error) { // _, err := sg.G.ExecCommand([]string{"ocr2:deploy", fmt.Sprintf("--minSubmissionValue=%d", minSubmissionValue), fmt.Sprintf("--maxSubmissionValue=%d", maxSubmissionValue), fmt.Sprintf("--decimals=%d", decimals), fmt.Sprintf("--name=%s", name), fmt.Sprintf("--link=%s", linkTokenAddress)}, *sg.options) From 63dc7ddb0403f25aad03beb7a7717bda6120f804 Mon Sep 17 00:00:00 2001 From: cfal Date: Thu, 20 Jul 2023 17:22:12 +0800 Subject: [PATCH 03/14] WIP2 --- integration-tests/common/client.go | 70 ++++++ integration-tests/common/common.go | 110 +++++---- integration-tests/common/gauntlet_common.go | 138 ------------ integration-tests/common/log.go | 24 ++ integration-tests/common/ocr2_config.go | 101 +++++++++ integration-tests/common/test_common.go | 95 -------- integration-tests/gauntlet/gauntlet.go | 234 ++++++++++++++++++++ integration-tests/ocr2_test.go | 104 +++++++++ integration-tests/smoke/ocr2_test.go | 54 ----- ops/gauntlet/gauntlet_cosmos.go | 225 ------------------- 10 files changed, 599 insertions(+), 556 deletions(-) create mode 100644 integration-tests/common/client.go delete mode 100644 integration-tests/common/gauntlet_common.go create mode 100644 integration-tests/common/log.go create mode 100644 integration-tests/common/ocr2_config.go delete mode 100644 integration-tests/common/test_common.go create mode 100644 integration-tests/gauntlet/gauntlet.go create mode 100644 integration-tests/ocr2_test.go delete mode 100644 integration-tests/smoke/ocr2_test.go delete mode 100644 ops/gauntlet/gauntlet_cosmos.go diff --git a/integration-tests/common/client.go b/integration-tests/common/client.go new file mode 100644 index 00000000..44971cab --- /dev/null +++ b/integration-tests/common/client.go @@ -0,0 +1,70 @@ +package common + +import ( + "github.com/smartcontractkit/chainlink-env/environment" + "github.com/smartcontractkit/chainlink/integration-tests/client" +) + +type ChainlinkClient struct { + ChainlinkNodes []*client.Chainlink + NodeKeys []client.NodeKeysBundle + bTypeAttr *client.BridgeTypeAttributes + bootstrapPeers []client.P2PData +} + +// CreateKeys Creates node keys and defines chain and nodes for each node +func NewChainlinkClient(env *environment.Environment, chainName string, chainId string, tendermintURL string) (*ChainlinkClient, error) { + nodes, err := client.ConnectChainlinkNodes(env) + if err != nil { + return nil, err + } + nodeKeys, _, err := client.CreateNodeKeysBundle(nodes, chainName, chainId) + if err != nil { + return nil, err + } + for _, n := range nodes { + _, _, err = n.CreateCosmosChain(&client.CosmosChainAttributes{ + ChainID: chainId, + Config: client.CosmosChainConfig{}, + }) + if err != nil { + return nil, err + } + _, _, err = n.CreateCosmosNode(&client.CosmosNodeAttributes{ + Name: chainName, + CosmosChainID: chainId, + TendermintURL: tendermintURL, + }) + if err != nil { + return nil, err + } + } + + return &ChainlinkClient{ + ChainlinkNodes: nodes, + NodeKeys: nodeKeys, + }, nil +} + +func (cc *ChainlinkClient) LoadOCR2Config(accountAddresses []string) (*OCR2Config, error) { + var offChaiNKeys []string + var onChaiNKeys []string + var peerIds []string + var txKeys []string + var cfgKeys []string + for i, key := range cc.NodeKeys { + offChaiNKeys = append(offChaiNKeys, key.OCR2Key.Data.Attributes.OffChainPublicKey) + peerIds = append(peerIds, key.PeerID) + txKeys = append(txKeys, accountAddresses[i]) + onChaiNKeys = append(onChaiNKeys, key.OCR2Key.Data.Attributes.OnChainPublicKey) + cfgKeys = append(cfgKeys, key.OCR2Key.Data.Attributes.ConfigPublicKey) + } + + var payload = TestOCR2Config + payload.Signers = onChaiNKeys + payload.Transmitters = txKeys + payload.OffchainConfig.OffchainPublicKeys = offChaiNKeys + payload.OffchainConfig.PeerIds = peerIds + payload.OffchainConfig.ConfigPublicKeys = cfgKeys + return &payload, nil +} diff --git a/integration-tests/common/common.go b/integration-tests/common/common.go index c4b2911e..9734207d 100644 --- a/integration-tests/common/common.go +++ b/integration-tests/common/common.go @@ -26,19 +26,34 @@ const ( ChainBlockTimeSoak = "2s" ) +var ( + observationSource = ` + val [type="bridge" name="bridge-coinmetrics" requestData=<{"data": {"from":"LINK","to":"USD"}}>] + parse [type="jsonparse" path="result"] + val -> parse + ` + juelsPerFeeCoinSource = `""" + sum [type="sum" values=<[451000]> ] + sum + """ + ` +) + type Common struct { - P2PPort string - ChainName string - ChainId string - NodeCount int - TTL time.Duration - Testnet bool - RPCUrl string - PrivateKey string - Account string - ClConfig map[string]any - K8Config *environment.Config - Env *environment.Environment + IsSoak bool + P2PPort string + ChainName string + ChainId string + NodeCount int + TTL time.Duration + RPCUrl string + PrivateKey string + Account string + ObservationSource string + JuelsPerFeeCoinSource string + ClConfig map[string]any + K8Config *environment.Config + Env *environment.Environment } // getEnv gets the environment variable if it exists and sets it for the remote runner @@ -50,48 +65,52 @@ func getEnv(v string) string { return val } -func New() *Common { - var err error - c := &Common{ - ChainName: chainName, - ChainId: chainID, - } +func getNodeCount() int { // Checking if count of OCR nodes is defined in ENV nodeCountSet := getEnv("NODE_COUNT") - if nodeCountSet != "" { - c.NodeCount, err = strconv.Atoi(nodeCountSet) - if err != nil { - panic(fmt.Sprintf("Please define a proper node count for the test: %v", err)) - } - } else { + if nodeCountSet == "" { panic("Please define NODE_COUNT") } + nodeCount, err := strconv.Atoi(nodeCountSet) + if err != nil { + panic(fmt.Sprintf("Please define a proper node count for the test: %v", err)) + } + return nodeCount +} - // Checking if TTL env var is set in ENV +func getTTL() time.Duration { ttlValue := getEnv("TTL") - if ttlValue != "" { - duration, err := time.ParseDuration(ttlValue) - if err != nil { - panic(fmt.Sprintf("Please define a proper duration for the test: %v", err)) - } - c.TTL, err = time.ParseDuration(*alias.ShortDur(duration)) - if err != nil { - panic(fmt.Sprintf("Please define a proper duration for the test: %v", err)) - } - } else { + if ttlValue == "" { panic("Please define TTL of env") } + duration, err := time.ParseDuration(ttlValue) + if err != nil { + panic(fmt.Sprintf("Please define a proper duration for the test: %v", err)) + } + t, err := time.ParseDuration(*alias.ShortDur(duration)) + if err != nil { + panic(fmt.Sprintf("Please define a proper duration for the test: %v", err)) + } + return t +} - // Setting optional parameters - c.L2RPCUrl = getEnv("L2_RPC_URL") // Fetch L2 RPC url if defined - c.Testnet = c.L2RPCUrl != "" - c.PrivateKey = getEnv("PRIVATE_KEY") - c.Account = getEnv("ACCOUNT") - +func NewCommon() *Common { + c := &Common{ + IsSoak: getEnv("SOAK") != "", + ChainName: chainName, + ChainId: chainID, + NodeCount: getNodeCount(), + TTL: getTTL(), + RPCUrl: getEnv("RPC_URL"), + PrivateKey: getEnv("PRIVATE_KEY"), + Account: getEnv("ACCOUNT"), + ObservationSource: observationSource, + JuelsPerFeeCoinSource: juelsPerFeeCoinSource, + } return c } -func (c *Common) Default(t *testing.T) { +func (c *Common) SetDefaultEnvironment(t *testing.T) { c.K8Config = &environment.Config{ NamespacePrefix: "cosmos-ocr", TTL: c.TTL, @@ -99,8 +118,11 @@ func (c *Common) Default(t *testing.T) { } // These can be uncommented when toml configuration is supposrted for cosmos in the chainlink node wasmdUrl := fmt.Sprintf("http://%s:%d", "tendermint-rpc", 26657) - if c.Testnet { - wasmdUrl = c.L2RPCUrl + //if c.Testnet { + //wasmdUrl = c.RPCUrl + //} + if c.RPCUrl != "" { + wasmdUrl = c.RPCUrl } baseTOML := fmt.Sprintf(`[[Cosmos]] Enabled = true diff --git a/integration-tests/common/gauntlet_common.go b/integration-tests/common/gauntlet_common.go deleted file mode 100644 index 0505e2d0..00000000 --- a/integration-tests/common/gauntlet_common.go +++ /dev/null @@ -1,138 +0,0 @@ -package common - -import ( - "encoding/json" - "errors" - "fmt" - "os" - - "github.com/smartcontractkit/chainlink-starknet/integration-tests/utils" -) - -var ( - ethAddressGoerli = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7" - nAccount string -) - -func (testState *Test) fundNodes() ([]string, error) { - l := utils.GetTestLogger(testState.T) - var nAccounts []string - var err error - for _, key := range testState.GetNodeKeys() { - if key.TXKey.Data.Attributes.StarkKey == "" { - return nil, errors.New("stark key can't be empty") - } - nAccount, err = testState.Cg.DeployAccountContract(100, key.TXKey.Data.Attributes.StarkKey) - if err != nil { - return nil, err - } - nAccounts = append(nAccounts, nAccount) - } - - if err != nil { - return nil, err - } - - for _, key := range nAccounts { - // We are not deploying in parallel here due to testnet limitations (429 too many requests) - l.Debug().Msg(fmt.Sprintf("Funding node with address: %s", key)) - _, err = testState.Cg.TransferToken(ethAddressGoerli, key, "100000000000000000") // Transferring 1 ETH to each node - if err != nil { - return nil, err - } - } - - return nAccounts, nil -} - -func (testState *Test) deployLinkToken() error { - _, err := testState.Cg.UploadContract("cw20_base") - if err != nil { - return err - } - - testState.LinkTokenAddr, err = testState.Cg.DeployLinkTokenContract() - if err != nil { - return err - } - err = os.Setenv("LINK", testState.LinkTokenAddr) - if err != nil { - return err - } - return nil -} - -func (testState *Test) deployAccessController() error { - var err error - testState.AccessControllerAddr, err = testState.Cg.DeployAccessControllerContract() - if err != nil { - return err - } - err = os.Setenv("BILLING_ACCESS_CONTROLLER", testState.AccessControllerAddr) - if err != nil { - return err - } - return nil -} - -func (testState *Test) setConfigDetails(ocrAddress string) error { - cfg, err := testState.LoadOCR2Config() - if err != nil { - return err - } - var parsedConfig []byte - parsedConfig, err = json.Marshal(cfg) - if err != nil { - return err - } - _, err = testState.Cg.SetConfigDetails(string(parsedConfig), ocrAddress) - return err -} - -func (testState *Test) DeployGauntlet(minSubmissionValue int64, maxSubmissionValue int64, decimals int, name string, observationPaymentGjuels int64, transmissionPaymentGjuels int64) error { - err := testState.Cg.InstallDependencies() - if err != nil { - return err - } - - testState.AccountAddresses, err = testState.fundNodes() - if err != nil { - return err - } - - err = testState.deployLinkToken() - if err != nil { - return err - } - - err = testState.deployAccessController() - if err != nil { - return err - } - - testState.OCRAddr, err = testState.Cg.DeployOCR2ControllerContract(minSubmissionValue, maxSubmissionValue, decimals, name, testState.LinkTokenAddr) - if err != nil { - return err - } - - testState.ProxyAddr, err = testState.Cg.DeployOCR2ProxyContract(testState.OCRAddr) - if err != nil { - return err - } - _, err = testState.Cg.AddAccess(testState.OCRAddr, testState.ProxyAddr) - if err != nil { - return err - } - - _, err = testState.Cg.MintLinkToken(testState.LinkTokenAddr, testState.OCRAddr, "100000000000000000000") - if err != nil { - return err - } - _, err = testState.Cg.SetOCRBilling(observationPaymentGjuels, transmissionPaymentGjuels, testState.OCRAddr) - if err != nil { - return err - } - - err = testState.setConfigDetails(testState.OCRAddr) - return err -} diff --git a/integration-tests/common/log.go b/integration-tests/common/log.go new file mode 100644 index 00000000..4cdbe4ae --- /dev/null +++ b/integration-tests/common/log.go @@ -0,0 +1,24 @@ +package common + +import ( + "os" + "testing" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/require" + + envConf "github.com/smartcontractkit/chainlink-env/config" +) + +// GetTestLogger TODO: This is a duplicate of the same function in chainlink-testing-framework. We should replace this with a call to the ctf version when chainlink-starknet is updated to use the latest ctf version. +// GetTestLogger instantiates a logger that takes into account the test context and the log level +func GetTestLogger(t *testing.T) zerolog.Logger { + lvlStr := os.Getenv(envConf.EnvVarLogLevel) + if lvlStr == "" { + lvlStr = "info" + } + lvl, err := zerolog.ParseLevel(lvlStr) + require.NoError(t, err, "error parsing log level") + l := zerolog.New(zerolog.NewTestWriter(t)).Output(zerolog.ConsoleWriter{Out: os.Stderr}).Level(lvl).With().Timestamp().Logger() + return l +} diff --git a/integration-tests/common/ocr2_config.go b/integration-tests/common/ocr2_config.go new file mode 100644 index 00000000..01747a84 --- /dev/null +++ b/integration-tests/common/ocr2_config.go @@ -0,0 +1,101 @@ +package common + +// OCR2Config Default config for OCR2 for starknet +// TODO: validate for cosmos +type OCR2Config struct { + F int `json:"f"` + Signers []string `json:"signers"` + Transmitters []string `json:"transmitters"` + OnchainConfig string `json:"onchainConfig"` + OffchainConfig *OffchainConfig `json:"offchainConfig"` + OffchainConfigVersion int `json:"offchainConfigVersion"` + Secret string `json:"secret"` +} + +type OffchainConfig struct { + DeltaProgressNanoseconds int64 `json:"deltaProgressNanoseconds"` + DeltaResendNanoseconds int64 `json:"deltaResendNanoseconds"` + DeltaRoundNanoseconds int64 `json:"deltaRoundNanoseconds"` + DeltaGraceNanoseconds int `json:"deltaGraceNanoseconds"` + DeltaStageNanoseconds int64 `json:"deltaStageNanoseconds"` + RMax int `json:"rMax"` + S []int `json:"s"` + OffchainPublicKeys []string `json:"offchainPublicKeys"` + PeerIds []string `json:"peerIds"` + ReportingPluginConfig *ReportingPluginConfig `json:"reportingPluginConfig"` + MaxDurationQueryNanoseconds int `json:"maxDurationQueryNanoseconds"` + MaxDurationObservationNanoseconds int `json:"maxDurationObservationNanoseconds"` + MaxDurationReportNanoseconds int `json:"maxDurationReportNanoseconds"` + MaxDurationShouldAcceptFinalizedReportNanoseconds int `json:"maxDurationShouldAcceptFinalizedReportNanoseconds"` + MaxDurationShouldTransmitAcceptedReportNanoseconds int `json:"maxDurationShouldTransmitAcceptedReportNanoseconds"` + ConfigPublicKeys []string `json:"configPublicKeys"` +} + +type ReportingPluginConfig struct { + AlphaReportInfinite bool `json:"alphaReportInfinite"` + AlphaReportPpb int `json:"alphaReportPpb"` + AlphaAcceptInfinite bool `json:"alphaAcceptInfinite"` + AlphaAcceptPpb int `json:"alphaAcceptPpb"` + DeltaCNanoseconds int `json:"deltaCNanoseconds"` +} + +var TestOCR2Config = OCR2Config{ + F: 1, + // Signers: onChainKeys, // user defined + // Transmitters: txKeys, // user defined + OnchainConfig: "", + OffchainConfig: &OffchainConfig{ + DeltaProgressNanoseconds: 8000000000, + DeltaResendNanoseconds: 30000000000, + DeltaRoundNanoseconds: 3000000000, + DeltaGraceNanoseconds: 1000000000, + DeltaStageNanoseconds: 20000000000, + RMax: 5, + S: []int{1, 2}, + // OffchainPublicKeys: offChainKeys, // user defined + // PeerIds: peerIds, // user defined + ReportingPluginConfig: &ReportingPluginConfig{ + AlphaReportInfinite: false, + AlphaReportPpb: 0, + AlphaAcceptInfinite: false, + AlphaAcceptPpb: 0, + DeltaCNanoseconds: 1000000000, + }, + MaxDurationQueryNanoseconds: 2000000000, + MaxDurationObservationNanoseconds: 1000000000, + MaxDurationReportNanoseconds: 2000000000, + MaxDurationShouldAcceptFinalizedReportNanoseconds: 2000000000, + MaxDurationShouldTransmitAcceptedReportNanoseconds: 2000000000, + // ConfigPublicKeys: cfgKeys, // user defined + }, + OffchainConfigVersion: 2, + Secret: "awe accuse polygon tonic depart acuity onyx inform bound gilbert expire", +} + +var TestOnKeys = []string{ + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603730", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603731", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603732", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603733", +} + +var TestTxKeys = []string{ + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603734", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603735", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603736", + "0x04cc1bfa99e282e434aef2815ca17337a923cd2c61cf0c7de5b326d7a8603737", +} + +var TestOffKeys = []string{ + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852090", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852091", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852092", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852093", +} + +var TestCfgKeys = []string{ + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852094", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852095", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852096", + "af400004fa5d02cd5170b5261032e71f2847ead36159cf8dee68affc3c852097", +} diff --git a/integration-tests/common/test_common.go b/integration-tests/common/test_common.go deleted file mode 100644 index d24fa644..00000000 --- a/integration-tests/common/test_common.go +++ /dev/null @@ -1,95 +0,0 @@ -package common - -import ( - "testing" - - "github.com/stretchr/testify/require" - - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - "github.com/smartcontractkit/chainlink/integration-tests/client" - - "github.com/smartcontractkit/chainlink-cosmos/ops/gauntlet" -) - -type Test struct { - // Devnet *devnet.CosmosDevnetClient - Cc *ChainlinkClient - // Cosmos *cosmos.Client //comes from relayer - // OCR2Client *ocr2.Client - Cg *gauntlet.CosmosGauntlet - mockServer *ctfClient.MockserverClient - L1RPCUrl string - Common *Common - LinkTokenAddr string - OCRAddr string - AccessControllerAddr string - ProxyAddr string - ObservationSource string - JuelsPerFeeCoinSource string - T *testing.T -} - -type ChainlinkClient struct { - NKeys []client.NodeKeysBundle - ChainlinkNodes []*client.Chainlink - bTypeAttr *client.BridgeTypeAttributes - bootstrapPeers []client.P2PData -} - -// DeployCluster Deploys and sets up config of the environment and nodes -func (testState *Test) DeployCluster() { - // lggr := logger.Nop() - testState.Cc = &ChainlinkClient{} - testState.ObservationSource = testState.GetDefaultObservationSource() - testState.JuelsPerFeeCoinSource = testState.GetDefaultJuelsPerFeeCoinSource() - testState.DeployEnv() - if testState.Common.Env.WillUseRemoteRunner() { - return // short circuit here if using a remote runner - } - // from starknet, may be useful later - // testState.SetupClients() - // if testState.Common.Testnet { - // testState.Common.Env.URLs[testState.Common.ServiceKeyL2][1] = testState.Common.L2RPCUrl - // } - // var err error - // testState.Cc.NKeys, testState.Cc.ChainlinkNodes, err = testState.Common.CreateKeys(testState.Common.Env) - // require.NoError(testState.T, err, "Creating chains and keys should not fail") - // testState.Cosmos, err = starknet.NewClient(testState.Common.ChainId, testState.Common.L2RPCUrl, lggr, &rpcRequestTimeout) - // require.NoError(testState.T, err, "Creating starknet client should not fail") - // testState.OCR2Client, err = ocr2.NewClient(testState.Starknet, lggr) - // require.NoError(testState.T, err, "Creating ocr2 client should not fail") - // if !testState.Common.Testnet { - // err = os.Setenv("PRIVATE_KEY", testState.GetDefaultPrivateKey()) - // require.NoError(testState.T, err, "Setting private key should not fail") - // err = os.Setenv("ACCOUNT", testState.GetDefaultWalletAddress()) - // require.NoError(testState.T, err, "Setting account address should not fail") - // testState.Devnet.AutoDumpState() // Auto dumping devnet state to avoid losing contracts on crash - // } -} - -// DeployEnv Deploys the environment -func (testState *Test) DeployEnv() { - err := testState.Common.Env.Run() - require.NoError(testState.T, err) - if testState.Common.Env.WillUseRemoteRunner() { - return // short circuit here if using a remote runner - } - testState.mockServer, err = ctfClient.ConnectMockServer(testState.Common.Env) - require.NoError(testState.T, err, "Creating mockserver clients shouldn't fail") -} - -func (testState *Test) GetDefaultObservationSource() string { - return ` - val [type = "bridge" name="bridge-mockserver"] - parse [type="jsonparse" path="data,result"] - val -> parse - ` -} - -func (testState *Test) GetDefaultJuelsPerFeeCoinSource() string { - return `""" - sum [type="sum" values=<[451000]> ] - sum - """ - ` -} diff --git a/integration-tests/gauntlet/gauntlet.go b/integration-tests/gauntlet/gauntlet.go new file mode 100644 index 00000000..3113972a --- /dev/null +++ b/integration-tests/gauntlet/gauntlet.go @@ -0,0 +1,234 @@ +package gauntlet + +import ( + "encoding/json" + "errors" + "fmt" + "os" + + "github.com/smartcontractkit/chainlink-testing-framework/gauntlet" +) + +var ( + cg *CosmosGauntlet +) + +type CosmosGauntlet struct { + dir string + G *gauntlet.Gauntlet + gr *GauntletResponse + options *gauntlet.ExecCommandOptions +} + +// GauntletResponse Default response output for cosmos gauntlet commands +type GauntletResponse struct { + Responses []struct { + Tx struct { + Hash string `json:"hash"` + Address string `json:"address"` + Status string `json:"status"` + CodeId int `json:"codeId"` + + Tx struct { + Address string `json:"address"` + Code string `json:"code"` + Result []string `json:"result"` + TransactionHash string `json:"transaction_hash"` + } `json:"tx"` + } `json:"tx"` + Contract string `json:"contract"` + } `json:"responses"` +} + +// NewCosmosGauntlet Creates a default gauntlet config +func NewCosmosGauntlet(workingDir string) (*CosmosGauntlet, error) { + g, err := gauntlet.NewGauntlet() + g.SetWorkingDir(workingDir) + if err != nil { + return nil, err + } + cg = &CosmosGauntlet{ + dir: workingDir, + G: g, + gr: &GauntletResponse{}, + options: &gauntlet.ExecCommandOptions{ + ErrHandling: []string{}, + CheckErrorsInRead: true, + }, + } + return cg, nil +} + +// FetchGauntletJsonOutput Parse gauntlet json response that is generated after yarn gauntlet command execution +func (cg *CosmosGauntlet) FetchGauntletJsonOutput() (*GauntletResponse, error) { + var payload = &GauntletResponse{} + gauntletOutput, err := os.ReadFile(cg.dir + "report.json") + if err != nil { + return payload, err + } + err = json.Unmarshal(gauntletOutput, &payload) + if err != nil { + return payload, err + } + return payload, nil +} + +// SetupNetwork Sets up a new network and sets the NODE_URL for Devnet / Cosmos RPC +func (cg *CosmosGauntlet) SetupNetwork(addr string) error { + cg.G.AddNetworkConfigVar("NODE_URL", addr) + err := cg.G.WriteNetworkConfigMap(cg.dir + "packages-ts/gauntlet-cosmos-contracts/networks/") + if err != nil { + return err + } + + return nil +} + +func (cg *CosmosGauntlet) InstallDependencies() error { + cg.G.Command = "yarn" + _, err := cg.G.ExecCommand([]string{"install"}, *cg.options) + if err != nil { + return err + } + cg.G.Command = "gauntlet" + return nil +} + +func (cg *CosmosGauntlet) UploadContract(name string) (int, error) { + _, err := cg.G.ExecCommand([]string{"upload", name}, *cg.options) + if err != nil { + return 0, err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return 0, err + } + return cg.gr.Responses[0].Tx.CodeId, nil +} + +//func (cg *CosmosGauntlet) DeployAccountContract(salt int64, pubKey string) (string, error) { +//_, err := cg.G.ExecCommand([]string{"account:deploy", fmt.Sprintf("--salt=%d", salt), fmt.Sprintf("--publicKey=%s", pubKey)}, *cg.options) +//if err != nil { +//return "", err +//} +//cg.gr, err = cg.FetchGauntletJsonOutput() +//if err != nil { +//return "", err +//} +//return cg.gr.Responses[0].Contract, nil +//} + +func (cg *CosmosGauntlet) DeployLinkTokenContract() (string, error) { + _, err := cg.G.ExecCommand([]string{"token:deploy"}, *cg.options) + if err != nil { + return "", err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return cg.gr.Responses[0].Contract, nil +} + +func (cg *CosmosGauntlet) MintLinkToken(token, to, amount string) (string, error) { + // _, err := cg.G.ExecCommand([]string{"ERC20:mint", fmt.Sprintf("--account=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *cg.options) + // if err != nil { + // return "", err + // } + // cg.gr, err = cg.FetchGauntletJsonOutput() + // if err != nil { + // return "", err + // } + // return cg.gr.Responses[0].Contract, nil + return "", errors.New("TODO") +} + +func (cg *CosmosGauntlet) TransferToken(token, to, amount string) (string, error) { + _, err := cg.G.ExecCommand([]string{"ERC20:transfer", fmt.Sprintf("--recipient=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *cg.options) + if err != nil { + return "", err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return cg.gr.Responses[0].Contract, nil +} + +func (cg *CosmosGauntlet) DeployOCR2ControllerContract(minSubmissionValue int64, maxSubmissionValue int64, decimals int, name string, linkTokenAddress string) (string, error) { + // _, err := cg.G.ExecCommand([]string{"ocr2:deploy", fmt.Sprintf("--minSubmissionValue=%d", minSubmissionValue), fmt.Sprintf("--maxSubmissionValue=%d", maxSubmissionValue), fmt.Sprintf("--decimals=%d", decimals), fmt.Sprintf("--name=%s", name), fmt.Sprintf("--link=%s", linkTokenAddress)}, *cg.options) + // if err != nil { + // return "", err + // } + // cg.gr, err = cg.FetchGauntletJsonOutput() + // if err != nil { + // return "", err + // } + // return cg.gr.Responses[0].Contract, nil + return "", errors.New("TODO") +} + +func (cg *CosmosGauntlet) DeployAccessControllerContract() (string, error) { + return "", errors.New("TODO") + // _, err := cg.G.ExecCommand([]string{"access_controller:deploy"}, *cg.options) + // if err != nil { + // return "", err + // } + // cg.gr, err = cg.FetchGauntletJsonOutput() + // if err != nil { + // return "", err + // } + // return cg.gr.Responses[0].Contract, nil +} + +func (cg *CosmosGauntlet) DeployOCR2ProxyContract(aggregator string) (string, error) { + // _, err := cg.G.ExecCommand([]string{"proxy:deploy", fmt.Sprintf("--address=%s", aggregator)}, *cg.options) + // if err != nil { + // return "", err + // } + // cg.gr, err = cg.FetchGauntletJsonOutput() + // if err != nil { + // return "", err + // } + // return cg.gr.Responses[0].Contract, nil + return "", errors.New("TODO") +} + +func (cg *CosmosGauntlet) SetOCRBilling(observationPaymentGjuels int64, transmissionPaymentGjuels int64, ocrAddress string) (string, error) { + // _, err := cg.G.ExecCommand([]string{"ocr2:set_billing", fmt.Sprintf("--observationPaymentGjuels=%d", observationPaymentGjuels), fmt.Sprintf("--transmissionPaymentGjuels=%d", transmissionPaymentGjuels), ocrAddress}, *cg.options) + // if err != nil { + // return "", err + // } + // cg.gr, err = cg.FetchGauntletJsonOutput() + // if err != nil { + // return "", err + // } + // return cg.gr.Responses[0].Contract, nil + return "", errors.New("TODO") +} + +func (cg *CosmosGauntlet) SetConfigDetails(cfg string, ocrAddress string) (string, error) { + // _, err := cg.G.ExecCommand([]string{"ocr2:set_config", "--input=" + cfg, ocrAddress}, *cg.options) + // if err != nil { + // return "", err + // } + // cg.gr, err = cg.FetchGauntletJsonOutput() + // if err != nil { + // return "", err + // } + // return cg.gr.Responses[0].Contract, nil + return "", errors.New("TODO") +} + +func (cg *CosmosGauntlet) AddOCR2Access(aggregator, address string) (string, error) { + // _, err := cg.G.ExecCommand([]string{"ocr2:add_access", fmt.Sprintf("--address=%s", address), aggregator}, *cg.options) + // if err != nil { + // return "", err + // } + // cg.gr, err = cg.FetchGauntletJsonOutput() + // if err != nil { + // return "", err + // } + // return cg.gr.Responses[0].Contract, nil + return "", errors.New("TODO") +} diff --git a/integration-tests/ocr2_test.go b/integration-tests/ocr2_test.go new file mode 100644 index 00000000..5281acdc --- /dev/null +++ b/integration-tests/ocr2_test.go @@ -0,0 +1,104 @@ +package ocr2_test + +import ( + "encoding/json" + "fmt" + "os" + "testing" + + "github.com/smartcontractkit/chainlink-cosmos/integration-tests/common" + "github.com/smartcontractkit/chainlink-cosmos/integration-tests/gauntlet" + "github.com/smartcontractkit/chainlink-cosmos/ops/utils" + "github.com/smartcontractkit/chainlink/integration-tests/actions" + + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +func TestOCRBasic(t *testing.T) { + logger := common.GetTestLogger(t) + commonConfig := common.NewCommon() + + gauntletWorkingDir := fmt.Sprintf("%s/", utils.ProjectRoot) + logger.Info().Str("working dir", gauntletWorkingDir).Msg("Initializing gauntlet") + + cg, err := gauntlet.NewCosmosGauntlet(gauntletWorkingDir) + require.NoError(t, err, "Could not create cosmos gauntlet") + + err = cg.InstallDependencies() + require.NoError(t, err, "Failed to install gauntlet dependencies") + + err = cg.SetupNetwork(commonConfig.RPCUrl) + require.NoError(t, err, "Setting up gauntlet network should not fail") + + // TODO: uncomment once we are ready to test rounds + // commonConfig.SetDefaultEnvironment(t) + + // TODO: fund nodes if necessary + + // store the cw20_base contract so we have the token contract, and then deploy the LINK token. + _, err = cg.UploadContract("cw20_base") + require.NoError(t, err, "Could not upload cw20_base contract") + + linkTokenAddress, err := cg.DeployLinkTokenContract() + require.NoError(t, err, "Could not deploy link token contract") + logger.Info().Str("address", linkTokenAddress).Msg("Deployed LINK token") + os.Setenv("LINK", linkTokenAddress) + + accessControllerAddress, err := cg.DeployAccessControllerContract() + require.NoError(t, err, "Could not deploy access controller") + logger.Info().Str("address", accessControllerAddress).Msg("Deployed access controller") + os.Setenv("BILLING_ACCESS_CONTROLLER", accessControllerAddress) + + minSubmissionValue := int64(0) + maxSubmissionValue := int64(100000000000) + decimals := 9 + name := "auto" + ocrAddress, err := cg.DeployOCR2ControllerContract(minSubmissionValue, maxSubmissionValue, decimals, name, linkTokenAddress) + require.NoError(t, err, "Could not deploy OCR2 controller contract") + logger.Info().Str("address", ocrAddress).Msg("Deployed OCR2 Controller contract") + + ocrProxyAddress, err := cg.DeployOCR2ProxyContract(ocrAddress) + require.NoError(t, err, "Could not deploy OCR2 proxy contract") + logger.Info().Str("address", ocrProxyAddress).Msg("Deployed OCR2 proxy contract") + + _, err = cg.AddOCR2Access(ocrAddress, ocrProxyAddress) + require.NoError(t, err, "Could not add OCR2 access") + logger.Info().Msg("Added OCR2 access") + + _, err = cg.MintLinkToken(linkTokenAddress, ocrAddress, "100000000000000000000") + require.NoError(t, err, "Could not mint LINK token") + + observationPaymentGjuels := int64(1) + transmissionPaymentGjuels := int64(1) + _, err = cg.SetOCRBilling(observationPaymentGjuels, transmissionPaymentGjuels, ocrAddress) + require.NoError(t, err, "Could not set OCR billing") + + chainlinkClient, err := common.NewChainlinkClient(commonConfig.Env, commonConfig.ChainName, commonConfig.ChainId, commonConfig.RPCUrl) + require.NoError(t, err, "Could not create chainlink client") + + cfg, err := chainlinkClient.LoadOCR2Config([]string{commonConfig.Account}) + require.NoError(t, err, "Could not load OCR2 config") + + var parsedConfig []byte + parsedConfig, err = json.Marshal(cfg) + require.NoError(t, err, "Could not parse JSON config") + + _, err = cg.SetConfigDetails(string(parsedConfig), ocrAddress) + require.NoError(t, err, "Could not set config details") + + //if !testState.Common.Testnet { + //testState.Devnet.AutoLoadState(testState.OCR2Client, testState.OCRAddr) + //} + //mockServerVal = 900000000 + //testState.SetUpNodes(mockServerVal) + + //err = testState.ValidateRounds(10, false) + //require.NoError(t, err, "Validating round should not fail") + + t.Cleanup(func() { + err = actions.TeardownSuite(t, commonConfig.Env, "./", nil, nil, zapcore.DPanicLevel, nil) + // err = actions.TeardownSuite(t, testState.Common.Env, utils.ProjectRoot, testState.Cc.ChainlinkNodes, nil, zapcore.ErrorLevel) + require.NoError(t, err, "Error tearing down environment") + }) +} diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go deleted file mode 100644 index 7262aecf..00000000 --- a/integration-tests/smoke/ocr2_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package smoke_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-cosmos/integration-tests/common" - "github.com/smartcontractkit/chainlink-cosmos/ops/gauntlet" - "github.com/smartcontractkit/chainlink-cosmos/ops/utils" - "github.com/smartcontractkit/chainlink/integration-tests/actions" -) - -var ( - err error - testState *common.Test - decimals = 9 - mockServerVal = 900000000 -) - -func TestOCRBasic(t *testing.T) { - testState = &common.Test{ - T: t, - } - testState.Common = common.New() - testState.Common.Default(t) - // Setting this to the root of the repo for cmd exec func for Gauntlet - testState.Cg, err = gauntlet.NewCosmosGauntlet(fmt.Sprintf("%s/", utils.ProjectRoot)) - require.NoError(t, err, "Could not get a new gauntlet struct") - testState.DeployCluster() - require.NoError(t, err, "Deploying cluster should not fail") - if testState.Common.Env.WillUseRemoteRunner() { - return // short circuit here if using a remote runner - } - err = testState.Cg.SetupNetwork(testState.Common.RPCUrl) - require.NoError(t, err, "Setting up gauntlet network should not fail") - err = testState.DeployGauntlet(0, 100000000000, decimals, "auto", 1, 1) - require.NoError(t, err, "Deploying contracts should not fail") - if !testState.Common.Testnet { - testState.Devnet.AutoLoadState(testState.OCR2Client, testState.OCRAddr) - } - testState.SetUpNodes(mockServerVal) - - err = testState.ValidateRounds(10, false) - require.NoError(t, err, "Validating round should not fail") - - t.Cleanup(func() { - err = actions.TeardownSuite(testState.T, testState.Common.Env, "./", nil, nil, zapcore.DPanicLevel, nil) - // err = actions.TeardownSuite(t, testState.Common.Env, utils.ProjectRoot, testState.Cc.ChainlinkNodes, nil, zapcore.ErrorLevel) - require.NoError(t, err, "Error tearing down environment") - }) -} diff --git a/ops/gauntlet/gauntlet_cosmos.go b/ops/gauntlet/gauntlet_cosmos.go deleted file mode 100644 index 3a520025..00000000 --- a/ops/gauntlet/gauntlet_cosmos.go +++ /dev/null @@ -1,225 +0,0 @@ -package gauntlet - -import ( - "encoding/json" - "os" - - "github.com/smartcontractkit/chainlink-testing-framework/gauntlet" -) - -var ( - cg *CosmosGauntlet -) - -type CosmosGauntlet struct { - dir string - G *gauntlet.Gauntlet - gr *GauntletResponse - options *gauntlet.ExecCommandOptions -} - -// GauntletResponse Default response output for cosmos gauntlet commands -type GauntletResponse struct { - Responses []struct { - Tx struct { - Hash string `json:"hash"` - Address string `json:"address"` - Status string `json:"status"` - CodeId int `json:"codeId"` - - Tx struct { - Address string `json:"address"` - Code string `json:"code"` - Result []string `json:"result"` - TransactionHash string `json:"transaction_hash"` - } `json:"tx"` - } `json:"tx"` - Contract string `json:"contract"` - } `json:"responses"` -} - -// NewCosmosGauntlet Creates a default gauntlet config -func NewCosmosGauntlet(workingDir string) (*CosmosGauntlet, error) { - g, err := gauntlet.NewGauntlet() - g.SetWorkingDir(workingDir) - if err != nil { - return nil, err - } - cg = &CosmosGauntlet{ - dir: workingDir, - G: g, - gr: &GauntletResponse{}, - options: &gauntlet.ExecCommandOptions{ - ErrHandling: []string{}, - CheckErrorsInRead: true, - }, - } - return cg, nil -} - -// FetchGauntletJsonOutput Parse gauntlet json response that is generated after yarn gauntlet command execution -func (cg *CosmosGauntlet) FetchGauntletJsonOutput() (*GauntletResponse, error) { - var payload = &GauntletResponse{} - gauntletOutput, err := os.ReadFile(cg.dir + "report.json") - if err != nil { - return payload, err - } - err = json.Unmarshal(gauntletOutput, &payload) - if err != nil { - return payload, err - } - return payload, nil -} - -// SetupNetwork Sets up a new network and sets the NODE_URL for Devnet / Cosmos RPC -func (sg *CosmosGauntlet) SetupNetwork(addr string) error { - sg.G.AddNetworkConfigVar("NODE_URL", addr) - err := sg.G.WriteNetworkConfigMap(sg.dir + "packages-ts/gauntlet-cosmos-contracts/networks/") - if err != nil { - return err - } - - return nil -} - -func (sg *CosmosGauntlet) InstallDependencies() error { - sg.G.Command = "yarn" - _, err := sg.G.ExecCommand([]string{"install"}, *sg.options) - if err != nil { - return err - } - sg.G.Command = "gauntlet" - return nil -} - -func (sg *CosmosGauntlet) UploadContract(name string) (int, error) { - _, err := sg.G.ExecCommand([]string{"upload", name}, *sg.options) - if err != nil { - return 0, err - } - sg.gr, err = sg.FetchGauntletJsonOutput() - if err != nil { - return 0, err - } - return sg.gr.Responses[0].Tx.CodeId, nil -} - -// func (sg *CosmosGauntlet) DeployAccountContract(salt int64, pubKey string) (string, error) { -// _, err := sg.G.ExecCommand([]string{"account:deploy", fmt.Sprintf("--salt=%d", salt), fmt.Sprintf("--publicKey=%s", pubKey)}, *sg.options) -// if err != nil { -// return "", err -// } -// sg.gr, err = sg.FetchGauntletJsonOutput() -// if err != nil { -// return "", err -// } -// return sg.gr.Responses[0].Contract, nil -// } - -func (sg *CosmosGauntlet) DeployLinkTokenContract() (string, error) { - _, err := sg.G.ExecCommand([]string{"token:deploy"}, *sg.options) - if err != nil { - return "", err - } - sg.gr, err = sg.FetchGauntletJsonOutput() - if err != nil { - return "", err - } - return sg.gr.Responses[0].Contract, nil -} - -// func (sg *CosmosGauntlet) MintLinkToken(token, to, amount string) (string, error) { -// _, err := sg.G.ExecCommand([]string{"ERC20:mint", fmt.Sprintf("--account=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *sg.options) -// if err != nil { -// return "", err -// } -// sg.gr, err = sg.FetchGauntletJsonOutput() -// if err != nil { -// return "", err -// } -// return sg.gr.Responses[0].Contract, nil -// } - -func (sg *CosmosGauntlet) TransferToken(token, to, amount string) (string, error) { - _, err := sg.G.ExecCommand([]string{"ERC20:transfer", fmt.Sprintf("--recipient=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *sg.options) - if err != nil { - return "", err - } - sg.gr, err = sg.FetchGauntletJsonOutput() - if err != nil { - return "", err - } - return sg.gr.Responses[0].Contract, nil -} - -// func (sg *CosmosGauntlet) DeployOCR2ControllerContract(minSubmissionValue int64, maxSubmissionValue int64, decimals int, name string, linkTokenAddress string) (string, error) { -// _, err := sg.G.ExecCommand([]string{"ocr2:deploy", fmt.Sprintf("--minSubmissionValue=%d", minSubmissionValue), fmt.Sprintf("--maxSubmissionValue=%d", maxSubmissionValue), fmt.Sprintf("--decimals=%d", decimals), fmt.Sprintf("--name=%s", name), fmt.Sprintf("--link=%s", linkTokenAddress)}, *sg.options) -// if err != nil { -// return "", err -// } -// sg.gr, err = sg.FetchGauntletJsonOutput() -// if err != nil { -// return "", err -// } -// return sg.gr.Responses[0].Contract, nil -// } - -// func (sg *CosmosGauntlet) DeployAccessControllerContract() (string, error) { -// _, err := sg.G.ExecCommand([]string{"access_controller:deploy"}, *sg.options) -// if err != nil { -// return "", err -// } -// sg.gr, err = sg.FetchGauntletJsonOutput() -// if err != nil { -// return "", err -// } -// return sg.gr.Responses[0].Contract, nil -// } - -// func (sg *CosmosGauntlet) DeployOCR2ProxyContract(aggregator string) (string, error) { -// _, err := sg.G.ExecCommand([]string{"proxy:deploy", fmt.Sprintf("--address=%s", aggregator)}, *sg.options) -// if err != nil { -// return "", err -// } -// sg.gr, err = sg.FetchGauntletJsonOutput() -// if err != nil { -// return "", err -// } -// return sg.gr.Responses[0].Contract, nil -// } - -// func (sg *CosmosGauntlet) SetOCRBilling(observationPaymentGjuels int64, transmissionPaymentGjuels int64, ocrAddress string) (string, error) { -// _, err := sg.G.ExecCommand([]string{"ocr2:set_billing", fmt.Sprintf("--observationPaymentGjuels=%d", observationPaymentGjuels), fmt.Sprintf("--transmissionPaymentGjuels=%d", transmissionPaymentGjuels), ocrAddress}, *sg.options) -// if err != nil { -// return "", err -// } -// sg.gr, err = sg.FetchGauntletJsonOutput() -// if err != nil { -// return "", err -// } -// return sg.gr.Responses[0].Contract, nil -// } - -// func (sg *CosmosGauntlet) SetConfigDetails(cfg string, ocrAddress string) (string, error) { -// _, err := sg.G.ExecCommand([]string{"ocr2:set_config", "--input=" + cfg, ocrAddress}, *sg.options) -// if err != nil { -// return "", err -// } -// sg.gr, err = sg.FetchGauntletJsonOutput() -// if err != nil { -// return "", err -// } -// return sg.gr.Responses[0].Contract, nil -// } - -// func (sg *CosmosGauntlet) AddAccess(aggregator, address string) (string, error) { -// _, err := sg.G.ExecCommand([]string{"ocr2:add_access", fmt.Sprintf("--address=%s", address), aggregator}, *sg.options) -// if err != nil { -// return "", err -// } -// sg.gr, err = sg.FetchGauntletJsonOutput() -// if err != nil { -// return "", err -// } -// return sg.gr.Responses[0].Contract, nil -// } From 4a45d3f34e3ff59ab0e81ee636482df924a55dc6 Mon Sep 17 00:00:00 2001 From: cfal Date: Mon, 24 Jul 2023 19:44:57 +0800 Subject: [PATCH 04/14] integration-tests: update env vars, upload access controller contract --- integration-tests/common/common.go | 12 +-- integration-tests/gauntlet/gauntlet.go | 126 ++++++++++++------------- integration-tests/ocr2_test.go | 6 +- 3 files changed, 71 insertions(+), 73 deletions(-) diff --git a/integration-tests/common/common.go b/integration-tests/common/common.go index 9734207d..dd9de27c 100644 --- a/integration-tests/common/common.go +++ b/integration-tests/common/common.go @@ -46,8 +46,8 @@ type Common struct { ChainId string NodeCount int TTL time.Duration - RPCUrl string - PrivateKey string + NodeUrl string + Mnemonic string Account string ObservationSource string JuelsPerFeeCoinSource string @@ -101,8 +101,8 @@ func NewCommon() *Common { ChainId: chainID, NodeCount: getNodeCount(), TTL: getTTL(), - RPCUrl: getEnv("RPC_URL"), - PrivateKey: getEnv("PRIVATE_KEY"), + NodeUrl: getEnv("NODE_URL"), + Mnemonic: getEnv("MNEMONIC"), Account: getEnv("ACCOUNT"), ObservationSource: observationSource, JuelsPerFeeCoinSource: juelsPerFeeCoinSource, @@ -121,8 +121,8 @@ func (c *Common) SetDefaultEnvironment(t *testing.T) { //if c.Testnet { //wasmdUrl = c.RPCUrl //} - if c.RPCUrl != "" { - wasmdUrl = c.RPCUrl + if c.NodeUrl != "" { + wasmdUrl = c.NodeUrl } baseTOML := fmt.Sprintf(`[[Cosmos]] Enabled = true diff --git a/integration-tests/gauntlet/gauntlet.go b/integration-tests/gauntlet/gauntlet.go index 3113972a..48656c8e 100644 --- a/integration-tests/gauntlet/gauntlet.go +++ b/integration-tests/gauntlet/gauntlet.go @@ -74,8 +74,9 @@ func (cg *CosmosGauntlet) FetchGauntletJsonOutput() (*GauntletResponse, error) { } // SetupNetwork Sets up a new network and sets the NODE_URL for Devnet / Cosmos RPC -func (cg *CosmosGauntlet) SetupNetwork(addr string) error { - cg.G.AddNetworkConfigVar("NODE_URL", addr) +func (cg *CosmosGauntlet) SetupNetwork(nodeUrl string, mnemonic string) error { + cg.G.AddNetworkConfigVar("NODE_URL", nodeUrl) + cg.G.AddNetworkConfigVar("MNEMONIC", mnemonic) err := cg.G.WriteNetworkConfigMap(cg.dir + "packages-ts/gauntlet-cosmos-contracts/networks/") if err != nil { return err @@ -94,8 +95,11 @@ func (cg *CosmosGauntlet) InstallDependencies() error { return nil } -func (cg *CosmosGauntlet) UploadContract(name string) (int, error) { - _, err := cg.G.ExecCommand([]string{"upload", name}, *cg.options) +func (cg *CosmosGauntlet) UploadContracts(names []string) (int, error) { + if names == nil { + names = []string{} + } + _, err := cg.G.ExecCommand(append([]string{"upload"}, names...), *cg.options) if err != nil { return 0, err } @@ -156,79 +160,73 @@ func (cg *CosmosGauntlet) TransferToken(token, to, amount string) (string, error } func (cg *CosmosGauntlet) DeployOCR2ControllerContract(minSubmissionValue int64, maxSubmissionValue int64, decimals int, name string, linkTokenAddress string) (string, error) { - // _, err := cg.G.ExecCommand([]string{"ocr2:deploy", fmt.Sprintf("--minSubmissionValue=%d", minSubmissionValue), fmt.Sprintf("--maxSubmissionValue=%d", maxSubmissionValue), fmt.Sprintf("--decimals=%d", decimals), fmt.Sprintf("--name=%s", name), fmt.Sprintf("--link=%s", linkTokenAddress)}, *cg.options) - // if err != nil { - // return "", err - // } - // cg.gr, err = cg.FetchGauntletJsonOutput() - // if err != nil { - // return "", err - // } - // return cg.gr.Responses[0].Contract, nil - return "", errors.New("TODO") + _, err := cg.G.ExecCommand([]string{"ocr2:deploy", fmt.Sprintf("--minSubmissionValue=%d", minSubmissionValue), fmt.Sprintf("--maxSubmissionValue=%d", maxSubmissionValue), fmt.Sprintf("--decimals=%d", decimals), fmt.Sprintf("--name=%s", name), fmt.Sprintf("--link=%s", linkTokenAddress)}, *cg.options) + if err != nil { + return "", err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return cg.gr.Responses[0].Contract, nil } func (cg *CosmosGauntlet) DeployAccessControllerContract() (string, error) { - return "", errors.New("TODO") - // _, err := cg.G.ExecCommand([]string{"access_controller:deploy"}, *cg.options) - // if err != nil { - // return "", err - // } - // cg.gr, err = cg.FetchGauntletJsonOutput() - // if err != nil { - // return "", err - // } - // return cg.gr.Responses[0].Contract, nil + _, err := cg.G.ExecCommand([]string{"access_controller:deploy"}, *cg.options) + if err != nil { + return "", err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return cg.gr.Responses[0].Contract, nil } func (cg *CosmosGauntlet) DeployOCR2ProxyContract(aggregator string) (string, error) { - // _, err := cg.G.ExecCommand([]string{"proxy:deploy", fmt.Sprintf("--address=%s", aggregator)}, *cg.options) - // if err != nil { - // return "", err - // } - // cg.gr, err = cg.FetchGauntletJsonOutput() - // if err != nil { - // return "", err - // } - // return cg.gr.Responses[0].Contract, nil - return "", errors.New("TODO") + _, err := cg.G.ExecCommand([]string{"proxy:deploy", fmt.Sprintf("--address=%s", aggregator)}, *cg.options) + if err != nil { + return "", err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return cg.gr.Responses[0].Contract, nil } func (cg *CosmosGauntlet) SetOCRBilling(observationPaymentGjuels int64, transmissionPaymentGjuels int64, ocrAddress string) (string, error) { - // _, err := cg.G.ExecCommand([]string{"ocr2:set_billing", fmt.Sprintf("--observationPaymentGjuels=%d", observationPaymentGjuels), fmt.Sprintf("--transmissionPaymentGjuels=%d", transmissionPaymentGjuels), ocrAddress}, *cg.options) - // if err != nil { - // return "", err - // } - // cg.gr, err = cg.FetchGauntletJsonOutput() - // if err != nil { - // return "", err - // } - // return cg.gr.Responses[0].Contract, nil - return "", errors.New("TODO") + _, err := cg.G.ExecCommand([]string{"ocr2:set_billing", fmt.Sprintf("--observationPaymentGjuels=%d", observationPaymentGjuels), fmt.Sprintf("--transmissionPaymentGjuels=%d", transmissionPaymentGjuels), ocrAddress}, *cg.options) + if err != nil { + return "", err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return cg.gr.Responses[0].Contract, nil } func (cg *CosmosGauntlet) SetConfigDetails(cfg string, ocrAddress string) (string, error) { - // _, err := cg.G.ExecCommand([]string{"ocr2:set_config", "--input=" + cfg, ocrAddress}, *cg.options) - // if err != nil { - // return "", err - // } - // cg.gr, err = cg.FetchGauntletJsonOutput() - // if err != nil { - // return "", err - // } - // return cg.gr.Responses[0].Contract, nil - return "", errors.New("TODO") + _, err := cg.G.ExecCommand([]string{"ocr2:set_config", "--input=" + cfg, ocrAddress}, *cg.options) + if err != nil { + return "", err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return cg.gr.Responses[0].Contract, nil } func (cg *CosmosGauntlet) AddOCR2Access(aggregator, address string) (string, error) { - // _, err := cg.G.ExecCommand([]string{"ocr2:add_access", fmt.Sprintf("--address=%s", address), aggregator}, *cg.options) - // if err != nil { - // return "", err - // } - // cg.gr, err = cg.FetchGauntletJsonOutput() - // if err != nil { - // return "", err - // } - // return cg.gr.Responses[0].Contract, nil - return "", errors.New("TODO") + _, err := cg.G.ExecCommand([]string{"ocr2:add_access", fmt.Sprintf("--address=%s", address), aggregator}, *cg.options) + if err != nil { + return "", err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return cg.gr.Responses[0].Contract, nil } diff --git a/integration-tests/ocr2_test.go b/integration-tests/ocr2_test.go index 5281acdc..4f589a36 100644 --- a/integration-tests/ocr2_test.go +++ b/integration-tests/ocr2_test.go @@ -28,7 +28,7 @@ func TestOCRBasic(t *testing.T) { err = cg.InstallDependencies() require.NoError(t, err, "Failed to install gauntlet dependencies") - err = cg.SetupNetwork(commonConfig.RPCUrl) + err = cg.SetupNetwork(commonConfig.NodeUrl, commonConfig.Mnemonic) require.NoError(t, err, "Setting up gauntlet network should not fail") // TODO: uncomment once we are ready to test rounds @@ -37,7 +37,7 @@ func TestOCRBasic(t *testing.T) { // TODO: fund nodes if necessary // store the cw20_base contract so we have the token contract, and then deploy the LINK token. - _, err = cg.UploadContract("cw20_base") + _, err = cg.UploadContracts(nil) require.NoError(t, err, "Could not upload cw20_base contract") linkTokenAddress, err := cg.DeployLinkTokenContract() @@ -74,7 +74,7 @@ func TestOCRBasic(t *testing.T) { _, err = cg.SetOCRBilling(observationPaymentGjuels, transmissionPaymentGjuels, ocrAddress) require.NoError(t, err, "Could not set OCR billing") - chainlinkClient, err := common.NewChainlinkClient(commonConfig.Env, commonConfig.ChainName, commonConfig.ChainId, commonConfig.RPCUrl) + chainlinkClient, err := common.NewChainlinkClient(commonConfig.Env, commonConfig.ChainName, commonConfig.ChainId, commonConfig.NodeUrl) require.NoError(t, err, "Could not create chainlink client") cfg, err := chainlinkClient.LoadOCR2Config([]string{commonConfig.Account}) From d1b69a9caf2bc3ec2f9f0a6c7a173a637cabd704 Mon Sep 17 00:00:00 2001 From: Calvin Wang Date: Mon, 31 Jul 2023 13:19:17 +1000 Subject: [PATCH 05/14] bump workspace-optimizer version --- scripts/build-contracts.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-contracts.sh b/scripts/build-contracts.sh index b85e2b26..28d1bd72 100755 --- a/scripts/build-contracts.sh +++ b/scripts/build-contracts.sh @@ -2,6 +2,6 @@ docker run --rm -v "$(pwd)":/code \ --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ - cosmwasm/workspace-optimizer:0.12.9 + cosmwasm/workspace-optimizer:0.13.0 # regenerate schemas for d in contracts/*/; do cd "$d"; cargo schema; cd ../..; done From cf863b5bee233b336ef213920eb93cb151113770 Mon Sep 17 00:00:00 2001 From: Calvin Wang Date: Mon, 31 Jul 2023 13:20:02 +1000 Subject: [PATCH 06/14] downgrade wasmd version back to 0.30 --- scripts/wasmd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wasmd.sh b/scripts/wasmd.sh index 3b2d6b66..c29fffb8 100755 --- a/scripts/wasmd.sh +++ b/scripts/wasmd.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash container_name="chainlink-cosmos.wasmd" -container_version="v0.40.1" +container_version="v0.30.0" genesis_account="wasm1lsagfzrm4gz28he4wunt63sts5xzmczwda8vl6" set -euo pipefail From 3a7cc54fe5ee8c09eb0d53f48efbed70a02a4277 Mon Sep 17 00:00:00 2001 From: Calvin Wang Date: Mon, 31 Jul 2023 13:31:36 +1000 Subject: [PATCH 07/14] gauntlet updates --- .../gauntlet-cosmos-contracts/package.json | 6 +- .../src/commands/contracts/link/mint.ts | 64 +++++++++++++++ .../ocr2/close/proposeOffchainConfig.ts | 6 ++ .../src/commands/contracts/ocr2/deploy.ts | 47 ++++++----- .../contracts/ocr2/inspection/inspect.ts | 6 +- .../contracts/ocr2/proposal/acceptProposal.ts | 5 +- .../contracts/ocr2/proposal/beginProposal.ts | 4 +- .../contracts/ocr2/proposeOffchainConfig.ts | 80 +++++++++++++------ .../src/commands/contracts/ocr2/setBilling.ts | 28 ++++--- .../commands/contracts/proxy_ocr2/deploy.ts | 2 +- .../src/commands/index.ts | 2 + packages-ts/gauntlet-cosmos/package.json | 10 +-- 12 files changed, 189 insertions(+), 71 deletions(-) create mode 100644 packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/link/mint.ts diff --git a/packages-ts/gauntlet-cosmos-contracts/package.json b/packages-ts/gauntlet-cosmos-contracts/package.json index aa977c00..36ef4a0c 100644 --- a/packages-ts/gauntlet-cosmos-contracts/package.json +++ b/packages-ts/gauntlet-cosmos-contracts/package.json @@ -35,9 +35,9 @@ "@chainlink/gauntlet-contracts-ocr2": "^0.2.3", "@chainlink/gauntlet-core": "0.2.0", "@chainlink/gauntlet-cosmos": "*", - "@cosmjs/cosmwasm-stargate": "^0.29.3", - "@cosmjs/encoding": "^0.29.3", - "@cosmjs/proto-signing": "^0.29.3", + "@cosmjs/cosmwasm-stargate": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", "ajv": "^8.6.3", "cosmjs-types": "^0.5.2" } diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/link/mint.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/link/mint.ts new file mode 100644 index 00000000..671953af --- /dev/null +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/link/mint.ts @@ -0,0 +1,64 @@ +import { AccAddress } from '@chainlink/gauntlet-cosmos' +import { logger } from '@chainlink/gauntlet-cosmos' +import { BN } from '@chainlink/gauntlet-core/dist/utils' +import { CATEGORIES, TOKEN_DECIMALS } from '../../../lib/constants' +import { AbstractInstruction, BeforeExecute, instructionToCommand } from '../../abstract/executionWrapper' + +type CommandInput = { + to: string + // Units in LINK + amount: string +} + +type ContractInput = { + recipient: string + amount: string +} + +const makeCommandInput = async (flags, args): Promise => { + if (flags.input) return flags.input as CommandInput + console.log(flags.to) + console.log(flags.amount) + console.log(args) + return { + to: flags.to, + amount: flags.amount, + } +} + +const validateInput = (input) => { + if (!AccAddress.validate(input.to)) throw new Error(`Invalid destination address`) + if (isNaN(Number(input.amount))) throw new Error(`Amount ${input.amount} is not a number`) + return true +} + +const makeContractInput = async (input: CommandInput): Promise => { + const amount = new BN(input.amount).mul(new BN(10).pow(new BN(TOKEN_DECIMALS))) + return { + recipient: input.to, + amount: amount.toString(), + } +} + +const beforeExecute: BeforeExecute = (_, input) => async () => { + logger.info( + `Minting ${input.contract.amount} (${input.user.amount}) Tokens to ${logger.styleAddress( + input.contract.recipient, + )}`, + ) +} + +const transferToken: AbstractInstruction = { + examples: [`yarn gauntlet cw20_base:mint --network= --to= --amount= `], + instruction: { + category: CATEGORIES.LINK, + contract: 'cw20_base', + function: 'mint', + }, + makeInput: makeCommandInput, + validateInput: validateInput, + makeContractInput: makeContractInput, + beforeExecute, +} + +export default instructionToCommand(transferToken) diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/close/proposeOffchainConfig.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/close/proposeOffchainConfig.ts index ea8d5d00..2c2c8882 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/close/proposeOffchainConfig.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/close/proposeOffchainConfig.ts @@ -14,7 +14,13 @@ export const EMPTY_SECRET = 'EMPTY' const makeInput = async (flags): Promise => { const defaultInput = { + f: 0, + signers: [], + transmitters: [], + onchainConfig: [], offchainConfig: makeEmptyOffchainConfig(), + offchainConfigVersion: 0, + secret: EMPTY_SECRET, randomSecret: EMPTY_SECRET, } if (flags.input) return { ...flags.input, ...defaultInput } diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/deploy.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/deploy.ts index 2e16e827..7449ec94 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/deploy.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/deploy.ts @@ -1,15 +1,10 @@ import { RDD } from '@chainlink/gauntlet-cosmos' +import { DeployOCR2, DeployOCR2Input } from '@chainlink/gauntlet-contracts-ocr2' import { instructionToCommand, AbstractInstruction } from '../../abstract/executionWrapper' import { CATEGORIES } from '../../../lib/constants' -type CommandInput = { - billingAccessController: string +export interface CommandInput extends DeployOCR2Input { requesterAccessController: string - linkToken: string - decimals: number - description: string - maxAnswer: string - minAnswer: string } type ContractInput = { @@ -24,18 +19,30 @@ type ContractInput = { const makeCommandInput = async (flags: any, args: string[]): Promise => { if (flags.input) return flags.input as CommandInput - const rdd = RDD.getRDD(flags.rdd) - const contract = args[0] - const aggregator = rdd.contracts[contract] - return { - maxAnswer: aggregator.maxSubmissionValue, - minAnswer: aggregator.minSubmissionValue, - decimals: aggregator.decimals, - description: aggregator.name, - billingAccessController: process.env.BILLING_ACCESS_CONTROLLER || '', - requesterAccessController: process.env.REQUESTER_ACCESS_CONTROLLER || '', - linkToken: process.env.LINK || '', + if (flags.rdd) { + const rdd = RDD.getRDD(flags.rdd) + const contract = args[0] + const aggregator = rdd.contracts[contract] + return { + maxAnswer: aggregator.maxSubmissionValue, + minAnswer: aggregator.minSubmissionValue, + decimals: aggregator.decimals, + description: aggregator.name, + billingAccessController: flags.billingAccessController || process.env.BILLING_ACCESS_CONTROLLER || '', + requesterAccessController: flags.requesterAccessController || process.env.REQUESTER_ACCESS_CONTROLLER || '', + linkToken: flags.link || process.env.LINK || '', + } } + flags.minSubmissionValue = parseInt(flags.minSubmissionValue) + flags.maxSubmissionValue = parseInt(flags.maxSubmissionValue) + flags.decimals = parseInt(flags.decimals) + + return { + ...DeployOCR2.makeUserInput(flags as DeployOCR2Input, args, process.env), + billingAccessController: flags.billingAccessController || process.env.BILLING_ACCESS_CONTROLLER || '', + requesterAccessController: flags.requesterAccessController || process.env.REQUESTER_ACCESS_CONTROLLER || '', + linkToken: flags.link || process.env.LINK || '', + } as CommandInput } const makeContractInput = async (input: CommandInput): Promise => { @@ -45,8 +52,8 @@ const makeContractInput = async (input: CommandInput): Promise => link_token: input.linkToken, decimals: input.decimals, description: input.description, - max_answer: input.maxAnswer, - min_answer: input.minAnswer, + max_answer: input.maxAnswer.toString(), + min_answer: input.minAnswer.toString(), } } diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/inspect.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/inspect.ts index a0955ae0..f6b23474 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/inspect.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/inspect.ts @@ -5,7 +5,7 @@ import { CONTRACT_LIST } from '../../../../lib/contracts' import { CATEGORIES, TOKEN_UNIT } from '../../../../lib/constants' import { InspectInstruction, instructionToInspectCommand } from '../../../abstract/inspectionWrapper' import { deserializeConfig } from '../../../../lib/encoding' -import { getOffchainConfigInput } from '../proposeOffchainConfig' +import { getSetConfigInputFromRDD } from '../proposeOffchainConfig' import { getLatestOCRConfigEvent } from '../../../../lib/inspection' // Command input and expected info is the same here @@ -38,6 +38,8 @@ const makeInput = async (flags: any, args: string[]): Promise async ( } try { - const proposalId = events.filter((element) => element.wasm[0].contract_address == context.contract)[0].wasm[0] - .proposal_id + const wasmEvent = events.filter(({ type }) => (type as any) == 'wasm')[0] + const proposalId = wasmEvent.attributes.find(({ key }) => key === 'proposal_id')?.value if (!proposalId) { throw new Error('ProposalId for the given contract does not exist inside events') diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposeOffchainConfig.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposeOffchainConfig.ts index 76319dbe..bcabfbce 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposeOffchainConfig.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposeOffchainConfig.ts @@ -6,12 +6,10 @@ import { CATEGORIES } from '../../../lib/constants' import { getLatestOCRConfigEvent } from '../../../lib/inspection' import { serializeOffchainConfig, deserializeConfig, generateSecretWords } from '../../../lib/encoding' import { logger, diff, longs } from '@chainlink/gauntlet-core/dist/utils' -import { encoding } from '@chainlink/gauntlet-contracts-ocr2' +import { SetConfig, encoding, SetConfigInput } from '@chainlink/gauntlet-contracts-ocr2' -export type CommandInput = { +export interface CommandInput extends SetConfigInput { proposalId: string - offchainConfig: encoding.OffchainConfig - randomSecret?: string } export type ContractInput = { @@ -20,18 +18,19 @@ export type ContractInput = { offchain_config: string } -export const getOffchainConfigInput = (rdd: any, contract: string): encoding.OffchainConfig => { +export const getSetConfigInputFromRDD = ( + rdd: any, + contract: string, +): { f: number; signers: string[]; transmitters: string[]; offchainConfig: encoding.OffchainConfig } => { const aggregator = rdd.contracts[contract] const config = aggregator.config const aggregatorOperators: any[] = aggregator.oracles.map((o) => rdd.operators[o.operator]) const operatorsPublicKeys = aggregatorOperators.map((o) => o.ocr2OffchainPublicKey[0].replace('ocr2off_cosmos_', '')) const operatorsPeerIds = aggregatorOperators.map((o) => o.peerId[0]) - const operatorConfigPublicKeys = aggregatorOperators.map((o) => - o.ocr2ConfigPublicKey[0].replace('ocr2cfg_cosmos_', ''), - ) + const operatorConfigPublicKeys = aggregatorOperators.map((o) => o.ocr2ConfigPublicKey[0]) - const input: encoding.OffchainConfig = { + const offchainConfig: encoding.OffchainConfig = { deltaProgressNanoseconds: time.durationToNanoseconds(config.deltaProgress).toNumber(), deltaResendNanoseconds: time.durationToNanoseconds(config.deltaResend).toNumber(), deltaRoundNanoseconds: time.durationToNanoseconds(config.deltaRound).toNumber(), @@ -59,7 +58,12 @@ export const getOffchainConfigInput = (rdd: any, contract: string): encoding.Off .toNumber(), configPublicKeys: operatorConfigPublicKeys, } - return input + return { + f: config.f, + signers: aggregatorOperators.map((o) => o.ocr2OnchainPublicKey[0]), + transmitters: aggregatorOperators.map((o) => o.ocrNodeAddress[0]), + offchainConfig, + } } export const prepareOffchainConfigForDiff = (config: encoding.OffchainConfig, extra?: Object): Object => { @@ -77,15 +81,36 @@ const makeCommandInput = async (flags: any, args: string[]): Promise = (context, inpu logger.info( `Important: The following secret was used to encode offchain config. You will need to provide it to approve the config proposal: - SECRET: ${input.user.randomSecret}`, + SECRET: ${input.user.secret}`, ) } const makeContractInput = async (input: CommandInput): Promise => { - const { offchainConfig } = await serializeOffchainConfig( - input.offchainConfig, - process.env.SECRET!, - input.randomSecret, + input.offchainConfig.offchainPublicKeys = input.offchainConfig.offchainPublicKeys.map((k) => + k.replace('ocr2off_cosmos_', ''), ) + if (input.offchainConfig.configPublicKeys) { + input.offchainConfig.configPublicKeys = input.offchainConfig.configPublicKeys?.map((k) => + k.replace('ocr2cfg_cosmos_', ''), + ) + } + + const { offchainConfig } = await serializeOffchainConfig(input.offchainConfig, input.secret, input.randomSecret) return { id: input.proposalId, - offchain_config_version: 2, + offchain_config_version: input.offchainConfigVersion, offchain_config: offchainConfig.toString('base64'), } } @@ -139,10 +169,10 @@ const afterExecute: AfterExecute = (_, input) => as logger.success(`Tx succeded at ${result.responses[0].tx.hash}`) logger.info( `Important: The following secret was used to encode offchain config. You will need to provide it to approve the config proposal: - SECRET: ${input.user.randomSecret}`, + SECRET: ${input.user.secret}`, ) return { - secret: input.user.randomSecret, + secret: input.user.secret, } } diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/setBilling.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/setBilling.ts index 778325a1..d1c9f6d6 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/setBilling.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/setBilling.ts @@ -1,13 +1,11 @@ import { BN } from '@chainlink/gauntlet-core/dist/utils' import { RDD } from '@chainlink/gauntlet-cosmos' import { AbstractInstruction, instructionToCommand } from '../../abstract/executionWrapper' +import { SetBilling, SetBillingInput } from '@chainlink/gauntlet-contracts-ocr2' import { CATEGORIES } from '../../../lib/constants' -import { CONTRACT_LIST } from '../../../lib/contracts' -type CommandInput = { +export interface CommandInput extends SetBillingInput { recommendedGasPriceMicro: string - observationPaymentGjuels: number - transmissionPaymentGjuels: number } type ContractInput = { @@ -20,14 +18,22 @@ type ContractInput = { const makeCommandInput = async (flags: any, args: string[]): Promise => { if (flags.input) return flags.input as CommandInput - const rdd = RDD.getRDD(flags.rdd) - const contract = args[0] - const billingInfo = rdd.contracts[contract]?.billing - return { - observationPaymentGjuels: billingInfo.observationPaymentGjuels, - transmissionPaymentGjuels: billingInfo.transmissionPaymentGjuels, - recommendedGasPriceMicro: billingInfo.recommendedGasPriceMicro, + + if (flags.rdd) { + const rdd = RDD.getRDD(flags.rdd) + const contract = args[0] + const billingInfo = rdd.contracts[contract]?.billing + return { + observationPaymentGjuels: billingInfo.observationPaymentGjuels, + transmissionPaymentGjuels: billingInfo.transmissionPaymentGjuels, + recommendedGasPriceMicro: billingInfo.recommendedGasPriceMicro, + } as CommandInput } + + return { + ...SetBilling.makeUserInput(flags, args, process.env), + recommendedGasPriceMicro: flags.recommendedGasPriceMicro, + } as CommandInput } const makeContractInput = async (input: CommandInput): Promise => { diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/proxy_ocr2/deploy.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/proxy_ocr2/deploy.ts index 555f2e45..f41999b3 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/proxy_ocr2/deploy.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/proxy_ocr2/deploy.ts @@ -1,4 +1,3 @@ -import { BN } from '@chainlink/gauntlet-core/dist/utils' import { AccAddress } from '@chainlink/gauntlet-cosmos' import { AbstractInstruction, instructionToCommand } from '../../abstract/executionWrapper' import { CATEGORIES } from '../../../lib/constants' @@ -34,6 +33,7 @@ const validateInput = (input: CommandInput): boolean => { } const deploy: AbstractInstruction = { + examples: ['yarn gauntlet proxy_ocr2:deploy --network= '], instruction: { category: CATEGORIES.PROXIES, contract: CONTRACT_LIST.PROXY_OCR_2, diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/index.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/index.ts index e12b4549..079e7384 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/index.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/index.ts @@ -1,6 +1,7 @@ import Upload from './tooling/upload' import Query from './tooling/query' import TransferLink from './contracts/link/transfer' +import MintLink from './contracts/link/mint' import DeployLink from './contracts/link/deploy' import OCR2 from './contracts/ocr2' import AccessController from './contracts/access_controller' @@ -16,6 +17,7 @@ export default [ Query, DeployLink, TransferLink, + MintLink, ...OCR2, ...AccessController, ...Flags, diff --git a/packages-ts/gauntlet-cosmos/package.json b/packages-ts/gauntlet-cosmos/package.json index 8b6ac3f6..c3298804 100644 --- a/packages-ts/gauntlet-cosmos/package.json +++ b/packages-ts/gauntlet-cosmos/package.json @@ -32,11 +32,11 @@ }, "dependencies": { "@chainlink/gauntlet-core": "0.2.0", - "@cosmjs/cosmwasm-stargate": "^0.29.3", - "@cosmjs/encoding": "^0.29.3", - "@cosmjs/ledger-amino": "^0.29.3", - "@cosmjs/proto-signing": "^0.29.3", - "@cosmjs/stargate": "^0.29.3", + "@cosmjs/cosmwasm-stargate": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/ledger-amino": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", "@ledgerhq/hw-transport-node-hid": "^6.20.0" } } From 0560a94925b944d5248b015a23d0b444af5f5dbb Mon Sep 17 00:00:00 2001 From: Calvin Wang Date: Mon, 31 Jul 2023 13:38:07 +1000 Subject: [PATCH 08/14] fix e2e tests wip --- integration-tests/common/ocr2_config.go | 2 -- integration-tests/gauntlet/gauntlet.go | 43 ++++++++++++++++--------- integration-tests/ocr2_test.go | 42 ++++++++++++++++-------- 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/integration-tests/common/ocr2_config.go b/integration-tests/common/ocr2_config.go index 01747a84..e2ecdea8 100644 --- a/integration-tests/common/ocr2_config.go +++ b/integration-tests/common/ocr2_config.go @@ -1,7 +1,5 @@ package common -// OCR2Config Default config for OCR2 for starknet -// TODO: validate for cosmos type OCR2Config struct { F int `json:"f"` Signers []string `json:"signers"` diff --git a/integration-tests/gauntlet/gauntlet.go b/integration-tests/gauntlet/gauntlet.go index 48656c8e..70ff3f20 100644 --- a/integration-tests/gauntlet/gauntlet.go +++ b/integration-tests/gauntlet/gauntlet.go @@ -2,7 +2,6 @@ package gauntlet import ( "encoding/json" - "errors" "fmt" "os" @@ -135,16 +134,15 @@ func (cg *CosmosGauntlet) DeployLinkTokenContract() (string, error) { } func (cg *CosmosGauntlet) MintLinkToken(token, to, amount string) (string, error) { - // _, err := cg.G.ExecCommand([]string{"ERC20:mint", fmt.Sprintf("--account=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *cg.options) - // if err != nil { - // return "", err - // } - // cg.gr, err = cg.FetchGauntletJsonOutput() - // if err != nil { - // return "", err - // } - // return cg.gr.Responses[0].Contract, nil - return "", errors.New("TODO") + _, err := cg.G.ExecCommand([]string{"cw20_base:mint", fmt.Sprintf("--to=%s", to), fmt.Sprintf("--amount=%s", amount), token}, *cg.options) + if err != nil { + return "", err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return cg.gr.Responses[0].Contract, nil } func (cg *CosmosGauntlet) TransferToken(token, to, amount string) (string, error) { @@ -184,7 +182,19 @@ func (cg *CosmosGauntlet) DeployAccessControllerContract() (string, error) { } func (cg *CosmosGauntlet) DeployOCR2ProxyContract(aggregator string) (string, error) { - _, err := cg.G.ExecCommand([]string{"proxy:deploy", fmt.Sprintf("--address=%s", aggregator)}, *cg.options) + _, err := cg.G.ExecCommand([]string{"proxy_ocr2:deploy", aggregator}, *cg.options) + if err != nil { + return "", err + } + cg.gr, err = cg.FetchGauntletJsonOutput() + if err != nil { + return "", err + } + return cg.gr.Responses[0].Contract, nil +} + +func (cg *CosmosGauntlet) SetOCRBilling(observationPaymentGjuels int64, transmissionPaymentGjuels int64, recommendedGasPriceMicro string, ocrAddress string) (string, error) { + _, err := cg.G.ExecCommand([]string{"ocr2:set_billing", fmt.Sprintf("--observationPaymentGjuels=%d", observationPaymentGjuels), fmt.Sprintf("--transmissionPaymentGjuels=%d", transmissionPaymentGjuels), fmt.Sprintf("--recommendedGasPriceMicro=%s", recommendedGasPriceMicro), ocrAddress}, *cg.options) if err != nil { return "", err } @@ -195,8 +205,8 @@ func (cg *CosmosGauntlet) DeployOCR2ProxyContract(aggregator string) (string, er return cg.gr.Responses[0].Contract, nil } -func (cg *CosmosGauntlet) SetOCRBilling(observationPaymentGjuels int64, transmissionPaymentGjuels int64, ocrAddress string) (string, error) { - _, err := cg.G.ExecCommand([]string{"ocr2:set_billing", fmt.Sprintf("--observationPaymentGjuels=%d", observationPaymentGjuels), fmt.Sprintf("--transmissionPaymentGjuels=%d", transmissionPaymentGjuels), ocrAddress}, *cg.options) +func (cg *CosmosGauntlet) BeginProposal(ocrAddress string) (string, error) { + _, err := cg.G.ExecCommand([]string{"ocr2:begin_proposal", ocrAddress}, *cg.options) if err != nil { return "", err } @@ -204,11 +214,12 @@ func (cg *CosmosGauntlet) SetOCRBilling(observationPaymentGjuels int64, transmis if err != nil { return "", err } + // TODO: return proposal id return cg.gr.Responses[0].Contract, nil } -func (cg *CosmosGauntlet) SetConfigDetails(cfg string, ocrAddress string) (string, error) { - _, err := cg.G.ExecCommand([]string{"ocr2:set_config", "--input=" + cfg, ocrAddress}, *cg.options) +func (cg *CosmosGauntlet) ProposeOffchainConfig(proposalId string, cfg string, ocrAddress string) (string, error) { + _, err := cg.G.ExecCommand([]string{"ocr2:propose_offchain_config", "--proposalId=" + proposalId, "--input=" + cfg, ocrAddress}, *cg.options) if err != nil { return "", err } diff --git a/integration-tests/ocr2_test.go b/integration-tests/ocr2_test.go index 4f589a36..bf79fabf 100644 --- a/integration-tests/ocr2_test.go +++ b/integration-tests/ocr2_test.go @@ -16,6 +16,7 @@ import ( ) func TestOCRBasic(t *testing.T) { + // Set up test logger := common.GetTestLogger(t) commonConfig := common.NewCommon() @@ -31,24 +32,29 @@ func TestOCRBasic(t *testing.T) { err = cg.SetupNetwork(commonConfig.NodeUrl, commonConfig.Mnemonic) require.NoError(t, err, "Setting up gauntlet network should not fail") - // TODO: uncomment once we are ready to test rounds - // commonConfig.SetDefaultEnvironment(t) + commonConfig.SetDefaultEnvironment(t) // TODO: fund nodes if necessary - // store the cw20_base contract so we have the token contract, and then deploy the LINK token. + // Upload contracts _, err = cg.UploadContracts(nil) - require.NoError(t, err, "Could not upload cw20_base contract") + require.NoError(t, err, "Could not upload contracts") + // Deploy contracts linkTokenAddress, err := cg.DeployLinkTokenContract() require.NoError(t, err, "Could not deploy link token contract") logger.Info().Str("address", linkTokenAddress).Msg("Deployed LINK token") os.Setenv("LINK", linkTokenAddress) - accessControllerAddress, err := cg.DeployAccessControllerContract() - require.NoError(t, err, "Could not deploy access controller") - logger.Info().Str("address", accessControllerAddress).Msg("Deployed access controller") - os.Setenv("BILLING_ACCESS_CONTROLLER", accessControllerAddress) + billingAccessControllerAddress, err := cg.DeployAccessControllerContract() + require.NoError(t, err, "Could not deploy billing access controller") + logger.Info().Str("address", billingAccessControllerAddress).Msg("Deployed billing access controller") + os.Setenv("BILLING_ACCESS_CONTROLLER", billingAccessControllerAddress) + + requesterAccessControllerAddress, err := cg.DeployAccessControllerContract() + require.NoError(t, err, "Could not deploy requester access controller") + logger.Info().Str("address", requesterAccessControllerAddress).Msg("Deployed requester access controller") + os.Setenv("REQUESTER_ACCESS_CONTROLLER", requesterAccessControllerAddress) minSubmissionValue := int64(0) maxSubmissionValue := int64(100000000000) @@ -62,18 +68,23 @@ func TestOCRBasic(t *testing.T) { require.NoError(t, err, "Could not deploy OCR2 proxy contract") logger.Info().Str("address", ocrProxyAddress).Msg("Deployed OCR2 proxy contract") - _, err = cg.AddOCR2Access(ocrAddress, ocrProxyAddress) - require.NoError(t, err, "Could not add OCR2 access") - logger.Info().Msg("Added OCR2 access") + // TODO: is this step necessary? + // _, err = cg.AddOCR2Access(ocrAddress, ocrProxyAddress) + // require.NoError(t, err, "Could not add OCR2 access") + // logger.Info().Msg("Added OCR2 access") + // Mint LINK tokens to aggregator _, err = cg.MintLinkToken(linkTokenAddress, ocrAddress, "100000000000000000000") require.NoError(t, err, "Could not mint LINK token") + // Set OCR2 Billing observationPaymentGjuels := int64(1) transmissionPaymentGjuels := int64(1) - _, err = cg.SetOCRBilling(observationPaymentGjuels, transmissionPaymentGjuels, ocrAddress) + recommendedGasPriceMicro := "1" + _, err = cg.SetOCRBilling(observationPaymentGjuels, transmissionPaymentGjuels, recommendedGasPriceMicro, ocrAddress) require.NoError(t, err, "Could not set OCR billing") + // OCR2 Config Proposal chainlinkClient, err := common.NewChainlinkClient(commonConfig.Env, commonConfig.ChainName, commonConfig.ChainId, commonConfig.NodeUrl) require.NoError(t, err, "Could not create chainlink client") @@ -84,8 +95,11 @@ func TestOCRBasic(t *testing.T) { parsedConfig, err = json.Marshal(cfg) require.NoError(t, err, "Could not parse JSON config") - _, err = cg.SetConfigDetails(string(parsedConfig), ocrAddress) - require.NoError(t, err, "Could not set config details") + proposalId, err := cg.BeginProposal(ocrAddress) + require.NoError(t, err, "Could not begin proposal") + + _, err = cg.ProposeOffchainConfig(proposalId, string(parsedConfig), ocrAddress) + require.NoError(t, err, "Could not propose config details") //if !testState.Common.Testnet { //testState.Devnet.AutoLoadState(testState.OCR2Client, testState.OCRAddr) From d6cd1be5af0e85e040e63e35e22f6aaee4c44781 Mon Sep 17 00:00:00 2001 From: cfal Date: Tue, 1 Aug 2023 20:06:27 +0800 Subject: [PATCH 09/14] packages-ts: upgrade cosmjs packages to 0.31.0 --- packages-ts/gauntlet-cosmos-contracts/package.json | 6 +++--- packages-ts/gauntlet-cosmos/package.json | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages-ts/gauntlet-cosmos-contracts/package.json b/packages-ts/gauntlet-cosmos-contracts/package.json index 36ef4a0c..78f28935 100644 --- a/packages-ts/gauntlet-cosmos-contracts/package.json +++ b/packages-ts/gauntlet-cosmos-contracts/package.json @@ -35,9 +35,9 @@ "@chainlink/gauntlet-contracts-ocr2": "^0.2.3", "@chainlink/gauntlet-core": "0.2.0", "@chainlink/gauntlet-cosmos": "*", - "@cosmjs/cosmwasm-stargate": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/cosmwasm-stargate": "^0.31.0", + "@cosmjs/encoding": "^0.31.0", + "@cosmjs/proto-signing": "^0.31.0", "ajv": "^8.6.3", "cosmjs-types": "^0.5.2" } diff --git a/packages-ts/gauntlet-cosmos/package.json b/packages-ts/gauntlet-cosmos/package.json index c3298804..38787c33 100644 --- a/packages-ts/gauntlet-cosmos/package.json +++ b/packages-ts/gauntlet-cosmos/package.json @@ -32,11 +32,11 @@ }, "dependencies": { "@chainlink/gauntlet-core": "0.2.0", - "@cosmjs/cosmwasm-stargate": "^0.29.5", - "@cosmjs/encoding": "^0.29.5", - "@cosmjs/ledger-amino": "^0.29.5", - "@cosmjs/proto-signing": "^0.29.5", - "@cosmjs/stargate": "^0.29.5", + "@cosmjs/cosmwasm-stargate": "^0.31.0", + "@cosmjs/encoding": "^0.31.0", + "@cosmjs/ledger-amino": "^0.31.0", + "@cosmjs/proto-signing": "^0.31.0", + "@cosmjs/stargate": "^0.31.0", "@ledgerhq/hw-transport-node-hid": "^6.20.0" } } From 782af5a5946318d5847148b1781dee4bae587ba0 Mon Sep 17 00:00:00 2001 From: cfal Date: Tue, 1 Aug 2023 20:20:22 +0800 Subject: [PATCH 10/14] packages-ts: fix searchTx to work with cosmjs 0.31.0 --- .../src/lib/inspection.ts | 2 +- packages-ts/gauntlet-cosmos/src/lib/provider.ts | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages-ts/gauntlet-cosmos-contracts/src/lib/inspection.ts b/packages-ts/gauntlet-cosmos-contracts/src/lib/inspection.ts index ac8a48a5..20d6b43a 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/lib/inspection.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/lib/inspection.ts @@ -16,7 +16,7 @@ export const getLatestOCRConfigEvent = async (provider: Client, contract: AccAdd const latestConfigDetails: any = await provider.queryContractSmart(contract, 'latest_config_details' as any) const setConfigTx = providerUtils.filterTxsByEvent( // TODO: there has to be a way to filter by tag for event then scan single block - await provider.searchTx({ height: latestConfigDetails.block_number }), + await provider.searchTx(`tx.height=${latestConfigDetails.block_number}`), 'wasm-set_config', ) diff --git a/packages-ts/gauntlet-cosmos/src/lib/provider.ts b/packages-ts/gauntlet-cosmos/src/lib/provider.ts index ec6d649d..4db5b98c 100644 --- a/packages-ts/gauntlet-cosmos/src/lib/provider.ts +++ b/packages-ts/gauntlet-cosmos/src/lib/provider.ts @@ -26,14 +26,12 @@ export const getLatestContractEvents = async ( event: string, contract: AccAddress, ): Promise => { - let txs = await provider.searchTx({ - tags: [ - { - key: `${event}.contract_address`, - value: contract, - }, - ], - }) // TODO: ORDER_BY_DESC + let txs = await provider.searchTx([ + { + key: `${event}.contract_address`, + value: contract, + }, + ]) // TODO: ORDER_BY_DESC if (txs.length === 0) return [] const events = txs.map(({ events }) => From cee18e1b4265efa5529dd62ead66652dacca750f Mon Sep 17 00:00:00 2001 From: cfal Date: Tue, 1 Aug 2023 20:20:29 +0800 Subject: [PATCH 11/14] yarn.lock: update --- yarn.lock | 854 ++++++++++-------------------------------------------- 1 file changed, 153 insertions(+), 701 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5a747779..c1d1c89c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -313,6 +313,23 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@chainlink/gauntlet-contracts-ocr2@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@chainlink/gauntlet-contracts-ocr2/-/gauntlet-contracts-ocr2-0.2.3.tgz#02865e9565863937dbc0a7905c419b8639ae4ddd" + integrity sha512-YI5MImjjwQ4V+RvcVvuz3x0Yl4oKMj9NANVJQbkzSi4Os+LLXHKKklcHICw5GPQUla8EBVelfTr5dMKY32KBLw== + dependencies: + "@chainlink/gauntlet-core" "*" + +"@chainlink/gauntlet-core@*": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@chainlink/gauntlet-core/-/gauntlet-core-0.7.0.tgz#80c103243d5d00e558a284a25e785d73dfd732db" + integrity sha512-dr5fh6W7pIkC4ngmHA3Hmn/2QIoWl1bwqunp3u12h1V34LsXaC+leeIFWf2VpHvsdkfXe9hJkY8N/79pxbGkTA== + dependencies: + "@ethersproject/keccak256" "^5.5.0" + axios "^0.24.0" + bn.js "^5.2.0" + protobufjs "^6.11.2" + "@chainlink/gauntlet-core@0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@chainlink/gauntlet-core/-/gauntlet-core-0.2.0.tgz#ffc67d4d91575b09d2a0471ea1b4b3b303ba47e1" @@ -523,178 +540,151 @@ "@noble/hashes" "^1.0.0" protobufjs "^6.8.8" -"@cosmjs/amino@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.29.3.tgz#5aa338a301ea970a93e15522706615efea507c10" - integrity sha512-BFz1++ERerIggiFc7iGHhGe1CeV3rCv8BvkoBQTBN/ZwzHOaKvqQj8smDlRGlQxX3HWlTwgiLN2A+OB5yX4ZRw== - dependencies: - "@cosmjs/crypto" "^0.29.3" - "@cosmjs/encoding" "^0.29.3" - "@cosmjs/math" "^0.29.3" - "@cosmjs/utils" "^0.29.3" - -"@cosmjs/cosmwasm-stargate@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.29.3.tgz#f6279fc6d590db01d6cb0f5cfae43bb2c88c279b" - integrity sha512-S13VlyWj2EGZ7hePT+kQkybksfjjYs/YffuZNVaD5P4CADiOcF52LGJcUCywyfYvC4RQYRVLOaq5hbAlLTUuew== - dependencies: - "@cosmjs/amino" "^0.29.3" - "@cosmjs/crypto" "^0.29.3" - "@cosmjs/encoding" "^0.29.3" - "@cosmjs/math" "^0.29.3" - "@cosmjs/proto-signing" "^0.29.3" - "@cosmjs/stargate" "^0.29.3" - "@cosmjs/tendermint-rpc" "^0.29.3" - "@cosmjs/utils" "^0.29.3" - cosmjs-types "^0.5.2" +"@cosmjs/amino@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.31.0.tgz#49b33047295002804ad51bdf7ec0c2c97f1b553d" + integrity sha512-xJ5CCEK7H79FTpOuEmlpSzVI+ZeYESTVvO3wHDgbnceIyAne3C68SvyaKqLUR4uJB0Z4q4+DZHbqW6itUiv4lA== + dependencies: + "@cosmjs/crypto" "^0.31.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/utils" "^0.31.0" + +"@cosmjs/cosmwasm-stargate@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.31.0.tgz#a9ea82471ca035b8d7f6ae640ad44b5f497be8c6" + integrity sha512-l6aX++3LhaAGZO46qIgrrNF40lYhOrdPfl35Z32ks6Wf3mwgbQEZwaxnoGzwUePY7/yaIiEFJ1JO6MlVPZVuag== + dependencies: + "@cosmjs/amino" "^0.31.0" + "@cosmjs/crypto" "^0.31.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/proto-signing" "^0.31.0" + "@cosmjs/stargate" "^0.31.0" + "@cosmjs/tendermint-rpc" "^0.31.0" + "@cosmjs/utils" "^0.31.0" + cosmjs-types "^0.8.0" long "^4.0.0" pako "^2.0.2" -"@cosmjs/crypto@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.29.3.tgz#4af0ac1264f1638c31d03cfcbedf2fca36e17890" - integrity sha512-dOCYLLEOnn5idNgoAcdQnuvFXZx/BmLnb2Mh8ZZtw6peFNvRePfaMX12HerngkLVAcLBc/V6pZHWoj9DBrsvng== +"@cosmjs/crypto@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.31.0.tgz#0be3867ada0155da19c45a51f5fde08e84f9ec4b" + integrity sha512-UaqCe6Tgh0pe1QlZ66E13t6FlIF86QrnBXXq+EN7Xe1Rouza3fJ1ojGlPleJZkBoq3tAyYVIOOqdZIxtVj/sIQ== dependencies: - "@cosmjs/encoding" "^0.29.3" - "@cosmjs/math" "^0.29.3" - "@cosmjs/utils" "^0.29.3" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/utils" "^0.31.0" "@noble/hashes" "^1" bn.js "^5.2.0" - elliptic "^6.5.3" - libsodium-wrappers "^0.7.6" + elliptic "^6.5.4" + libsodium-wrappers-sumo "^0.7.11" -"@cosmjs/encoding@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.29.3.tgz#191fe1192d78ac0f9eb01b6e0aa4ba976cfb2c7a" - integrity sha512-K6CTcDGovwzF3QOmLm9mWwjcu4Md64zCOBYgVK3boGbsaExP/6YAjT22e+yDsReXWlEUtSVCjqCC/9EEcwmYmg== +"@cosmjs/encoding@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.31.0.tgz#9a6fd80b59c35fc20638a6436128ad0be681eafc" + integrity sha512-NYGQDRxT7MIRSlcbAezwxK0FqnaSPKCH7O32cmfpHNWorFxhy9lwmBoCvoe59Kd0HmArI4h+NGzLEfX3OLnA4Q== dependencies: base64-js "^1.3.0" bech32 "^1.1.4" readonly-date "^1.0.0" -"@cosmjs/json-rpc@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/json-rpc/-/json-rpc-0.29.3.tgz#17d99b71410c24e082d492d307ad25463d0a72d1" - integrity sha512-GP3qSMxVcoTQFI1/tWQDou843ZO0s51LaT+oaSr7F6C4XNCBv9BnSiVteijeZOaIPmhSBMnZs+7QDORlDHpS7A== +"@cosmjs/json-rpc@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/json-rpc/-/json-rpc-0.31.0.tgz#38fda21188f2046db4a111fb5463ccde3c3751d7" + integrity sha512-Ix2Cil2qysiLNrX+E0w3vtwCrqxGVq8jklpLA7B2vtMrw7tru/rS65fdFSy8ep0wUNLL6Ud32VXa5K0YObDOMA== dependencies: - "@cosmjs/stream" "^0.29.3" + "@cosmjs/stream" "^0.31.0" xstream "^11.14.0" -"@cosmjs/ledger-amino@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/ledger-amino/-/ledger-amino-0.29.3.tgz#8206a0c79c1a6a55312f87d43afd2c9a711f870f" - integrity sha512-PBDMWPfH8K3dYR020o2OZkV/96eUXOytaRnEYw5nItMJhUKPQZ/FKaCuvi0GiJluQw/39Y/cI4IIlVKCDXWUIQ== +"@cosmjs/ledger-amino@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/ledger-amino/-/ledger-amino-0.31.0.tgz#38ba1f8e6c95981a3698c4536a49d63aef7d30f0" + integrity sha512-+YPZ5BLiD9skAIxpnA9U9o4CbxBdQvOII2CCPG22TUDaGo+pgaEi5+cAAudCdW98GsUm5ntgGIbpXCbubBW9QA== dependencies: - "@cosmjs/amino" "^0.29.3" - "@cosmjs/crypto" "^0.29.3" - "@cosmjs/encoding" "^0.29.3" - "@cosmjs/math" "^0.29.3" - "@cosmjs/utils" "^0.29.3" + "@cosmjs/amino" "^0.31.0" + "@cosmjs/crypto" "^0.31.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/utils" "^0.31.0" ledger-cosmos-js "^2.1.8" semver "^7.3.2" -"@cosmjs/math@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.29.3.tgz#29f98f6529f3d7654f1af85b329b48482eabbecb" - integrity sha512-4HGHqS+Yn81dZLOAYcDSQbROBD1a7ETW3ur5hziCTXMjZFILRJ3w71PlFUVppVb2u3kRDBBXuYHvZ6/V0M0nrg== +"@cosmjs/math@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.31.0.tgz#c9fc5f8191df7c2375945d2eacce327dfbf26414" + integrity sha512-Sb/8Ry/+gKJaYiV6X8q45kxXC9FoV98XCY1WXtu0JQwOi61VCG2VXsURQnVvZ/EhR/CuT/swOlNKrqEs3da0fw== dependencies: bn.js "^5.2.0" -"@cosmjs/proto-signing@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.29.3.tgz#fa5ed609ed2a0007d8d5eacbeb1f5a89ba1b77ff" - integrity sha512-Ai3l9THjMOrLJ4Ebn1Dgptwg6W5ZIRJqtnJjijHhGwTVC1WT0WdYU3aMZ7+PwubcA/cA1rH4ZTK7jrfYbra63g== - dependencies: - "@cosmjs/amino" "^0.29.3" - "@cosmjs/crypto" "^0.29.3" - "@cosmjs/encoding" "^0.29.3" - "@cosmjs/math" "^0.29.3" - "@cosmjs/utils" "^0.29.3" - cosmjs-types "^0.5.2" +"@cosmjs/proto-signing@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.31.0.tgz#7056963457cd967f53f56c2ab4491638e5ade2c0" + integrity sha512-JNlyOJRkn8EKB9mCthkjr6lVX6eyVQ09PFdmB4/DR874E62dFTvQ+YvyKMAgN7K7Dcjj26dVlAD3f6Xs7YOGDg== + dependencies: + "@cosmjs/amino" "^0.31.0" + "@cosmjs/crypto" "^0.31.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/utils" "^0.31.0" + cosmjs-types "^0.8.0" long "^4.0.0" -"@cosmjs/socket@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/socket/-/socket-0.29.3.tgz#0c3fcf16066946c43a7666516ee0edc096ff977c" - integrity sha512-yP35avUsBId/HUBVPRg8z1KmW2iTjMNzflBcFVuTbVoDZrK9DHIlAsB8lV+XKIKPqqECvEq2Dtb1Z+XDy1WBEA== +"@cosmjs/socket@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/socket/-/socket-0.31.0.tgz#ffcae48251a68b4a1c37a1c996d8b123cd8ad5ac" + integrity sha512-WDh9gTyiP3OCXvSAJJn33+Ef3XqMWag+bpR1TdMBxTmlTxuvU+kPy4cf6P2OF+jkkUBEA5Se2EAju0eFbJMT+w== dependencies: - "@cosmjs/stream" "^0.29.3" + "@cosmjs/stream" "^0.31.0" isomorphic-ws "^4.0.1" ws "^7" xstream "^11.14.0" -"@cosmjs/stargate@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/stargate/-/stargate-0.29.3.tgz#9bd303bfd32a7399a233e662864e7cc32e2607af" - integrity sha512-455TgXStCi6E8KDjnhDAM8wt6aLSjobH4Dixvd7Up1DfCH6UB9NkC/G0fMJANNcNXMaM4wSX14niTXwD1d31BA== +"@cosmjs/stargate@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/stargate/-/stargate-0.31.0.tgz#a7df1eaf1363513529607abaa52a5045aaaee0fd" + integrity sha512-GYhk9lzZPj/QmYHC0VV/4AMoRzVcOP+EnB1YZCoWlBdLuVmpBYKRagJqWIrIwdk1E0gF2ZoESd2TYfdh1fqIpg== dependencies: "@confio/ics23" "^0.6.8" - "@cosmjs/amino" "^0.29.3" - "@cosmjs/encoding" "^0.29.3" - "@cosmjs/math" "^0.29.3" - "@cosmjs/proto-signing" "^0.29.3" - "@cosmjs/stream" "^0.29.3" - "@cosmjs/tendermint-rpc" "^0.29.3" - "@cosmjs/utils" "^0.29.3" - cosmjs-types "^0.5.2" + "@cosmjs/amino" "^0.31.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/proto-signing" "^0.31.0" + "@cosmjs/stream" "^0.31.0" + "@cosmjs/tendermint-rpc" "^0.31.0" + "@cosmjs/utils" "^0.31.0" + cosmjs-types "^0.8.0" long "^4.0.0" protobufjs "~6.11.3" xstream "^11.14.0" -"@cosmjs/stream@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/stream/-/stream-0.29.3.tgz#9d9a9ec952cbc96f2e524204c4833980e314e6cd" - integrity sha512-0fbKvslZjNyuVe43cB9NDSqlBUXOHG84wGry4HmYfwayRtHr1CDWH5nR3v04eG0/prmZht8J3TgPsfWozIP+cw== +"@cosmjs/stream@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/stream/-/stream-0.31.0.tgz#7faf0f5ccd5ceffdd3b5d9fb81e292bb7a930b2c" + integrity sha512-Y+aSHwhHkLGIaQOdqRob+yga2zr9ifl9gZDKD+B7+R5pdWN5f2TTDhYWxA6YZcZ6xRmfr7u8a7tDh7iYLC/zKA== dependencies: xstream "^11.14.0" -"@cosmjs/tendermint-rpc@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.29.3.tgz#054f80e5095cdf328d98fa7bcf23cd785435d247" - integrity sha512-4l3VacUMQdyGGqfzbZ02kEwlVdMVOdAeWJt2euoVdfUR/HT+TTzQrrL+ORj9PEooLLtwtMl9dqms8uEiblYBDg== - dependencies: - "@cosmjs/crypto" "^0.29.3" - "@cosmjs/encoding" "^0.29.3" - "@cosmjs/json-rpc" "^0.29.3" - "@cosmjs/math" "^0.29.3" - "@cosmjs/socket" "^0.29.3" - "@cosmjs/stream" "^0.29.3" - "@cosmjs/utils" "^0.29.3" +"@cosmjs/tendermint-rpc@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.31.0.tgz#df82f634ff08fc377dfdccea43a31d92b5b0eaf1" + integrity sha512-yo9xbeuI6UoEKIhFZ9g0dvUKLqnBzwdpEc/uldQygQc51j38gQVwFko+6sjmhieJqRYYvrYumcbJMiV6GFM9aA== + dependencies: + "@cosmjs/crypto" "^0.31.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/json-rpc" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/socket" "^0.31.0" + "@cosmjs/stream" "^0.31.0" + "@cosmjs/utils" "^0.31.0" axios "^0.21.2" readonly-date "^1.0.0" xstream "^11.14.0" -"@cosmjs/utils@^0.29.3": - version "0.29.3" - resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.29.3.tgz#d7e1f381267e61b7d3219ebd75d46defc397cd43" - integrity sha512-UuKoBN2xiRXcBpz7jzCwagKhOnLOsRmR8mu3IzY+Yx38i8rW52FSXMbxC/yE83X0vLea+zgMQFPwv0gy4QWUJw== - -"@cspotcode/source-map-consumer@0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" - integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== - -"@cspotcode/source-map-support@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" - integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== - dependencies: - "@cspotcode/source-map-consumer" "0.8.0" - -"@eslint/eslintrc@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.0.tgz#7ce1547a5c46dfe56e1e45c3c9ed18038c721c6a" - integrity sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.3.1" - globals "^13.9.0" - ignore "^4.0.6" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.0.4" - strip-json-comments "^3.1.1" +"@cosmjs/utils@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.31.0.tgz#3a7ac16856dcff63bbf1bb11e31f975f71ef4f21" + integrity sha512-nNcycZWUYLNJlrIXgpcgVRqdl6BXjF4YlXdxobQWpW9Tikk61bEGeAFhDYtC0PwHlokCNw0KxWiHGJL4nL7Q5A== "@ethersproject/bytes@^5.5.0": version "5.5.0" @@ -716,20 +706,6 @@ resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== -"@humanwhocodes/config-array@^0.9.2": - version "0.9.5" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" - integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.4" - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1138,26 +1114,6 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== -"@tsconfig/node10@^1.0.7": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" - integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== - -"@tsconfig/node12@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" - integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== - -"@tsconfig/node14@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" - integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== - -"@tsconfig/node16@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" - integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== - "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.18" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.18.tgz#1a29abcc411a9c05e2094c98f9a1b7da6cdf49f8" @@ -1191,26 +1147,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/eslint-plugin-prettier@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.0.tgz#451b5e1e5f148a38dc41e9c5b61d45cd2e97af2c" - integrity sha512-6/UIuz99F0IvtDez4U3bRwAmN4VKnuw10Ibblf0iZhtNbmbonMSLqs/qqsXrGIAWvjy+vXqYwOljgtLhrETSMg== - dependencies: - "@types/eslint" "*" - -"@types/eslint@*", "@types/eslint@^8.2.1": - version "8.4.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" - integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== - "@types/graceful-fs@^4.1.2": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" @@ -1252,11 +1188,6 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.9": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== - "@types/long@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" @@ -1267,11 +1198,6 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== -"@types/mocha@^9.0.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.0.tgz#baf17ab2cca3fcce2d322ebc30454bff487efad5" - integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg== - "@types/node@*", "@types/node@>=13.7.0": version "17.0.16" resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.16.tgz#e3733f46797b9df9e853ca9f719c8a6f7b84cd26" @@ -1282,11 +1208,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.43.tgz#6cf47894da4a4748c62fccf720ba269e1b1ff5a4" integrity sha512-HCfJdaYqJX3BCzeihgZrD7b85Cu05OC/GVJ4kEYIflwUs4jbnUlLLWoq7hw1LBcdvUyehO+gr6P5JQ895/2ZfA== -"@types/node@^16.11.13": - version "16.11.26" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.26.tgz#63d204d136c9916fb4dcd1b50f9740fe86884e47" - integrity sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ== - "@types/node@^17.0.17": version "17.0.17" resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.17.tgz#a8ddf6e0c2341718d74ee3dc413a13a042c45a0c" @@ -1297,7 +1218,7 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== -"@types/prettier@^2.0.0", "@types/prettier@^2.4.2": +"@types/prettier@^2.0.0": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.4.tgz#5d9b63132df54d8909fce1c3f8ca260fdd693e17" integrity sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA== @@ -1324,86 +1245,6 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.8.1": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz#2809052b85911ced9c54a60dac10e515e9114497" - integrity sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ== - dependencies: - "@typescript-eslint/scope-manager" "5.13.0" - "@typescript-eslint/type-utils" "5.13.0" - "@typescript-eslint/utils" "5.13.0" - debug "^4.3.2" - functional-red-black-tree "^1.0.1" - ignore "^5.1.8" - regexpp "^3.2.0" - semver "^7.3.5" - tsutils "^3.21.0" - -"@typescript-eslint/parser@^5.8.1": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.13.0.tgz#0394ed8f2f849273c0bf4b811994d177112ced5c" - integrity sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg== - dependencies: - "@typescript-eslint/scope-manager" "5.13.0" - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/typescript-estree" "5.13.0" - debug "^4.3.2" - -"@typescript-eslint/scope-manager@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz#cf6aff61ca497cb19f0397eea8444a58f46156b6" - integrity sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA== - dependencies: - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/visitor-keys" "5.13.0" - -"@typescript-eslint/type-utils@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz#b0efd45c85b7bab1125c97b752cab3a86c7b615d" - integrity sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg== - dependencies: - "@typescript-eslint/utils" "5.13.0" - debug "^4.3.2" - tsutils "^3.21.0" - -"@typescript-eslint/types@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.13.0.tgz#da1de4ae905b1b9ff682cab0bed6b2e3be9c04e5" - integrity sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg== - -"@typescript-eslint/typescript-estree@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz#b37c07b748ff030a3e93d87c842714e020b78141" - integrity sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA== - dependencies: - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/visitor-keys" "5.13.0" - debug "^4.3.2" - globby "^11.0.4" - is-glob "^4.0.3" - semver "^7.3.5" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.13.0.tgz#2328feca700eb02837298339a2e49c46b41bd0af" - integrity sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ== - dependencies: - "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.13.0" - "@typescript-eslint/types" "5.13.0" - "@typescript-eslint/typescript-estree" "5.13.0" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - -"@typescript-eslint/visitor-keys@5.13.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz#f45ff55bcce16403b221ac9240fbeeae4764f0fd" - integrity sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g== - dependencies: - "@typescript-eslint/types" "5.13.0" - eslint-visitor-keys "^3.0.0" - abab@^2.0.3, abab@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" @@ -1417,27 +1258,17 @@ acorn-globals@^6.0.0: acorn "^7.1.1" acorn-walk "^7.1.1" -acorn-jsx@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - acorn-walk@^7.1.1: version "7.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - acorn@^7.1.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.2.4, acorn@^8.4.1, acorn@^8.7.0: +acorn@^8.2.4: version "8.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== @@ -1449,16 +1280,6 @@ agent-base@6: dependencies: debug "4" -ajv@^6.10.0, ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - ajv@^8.6.3: version "8.10.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" @@ -1546,11 +1367,6 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -2056,10 +1872,13 @@ cosmjs-types@^0.5.2: long "^4.0.0" protobufjs "~6.11.2" -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cosmjs-types@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.8.0.tgz#2ed78f3e990f770229726f95f3ef5bf9e2b6859b" + integrity sha512-Q2Mj95Fl0PYMWEhA2LuGEIhipF7mQwd9gTQ85DdP9jjjopeoGaDxvmPa5nakNzsq7FnO1DMTatXTAx6bxMH7Lg== + dependencies: + long "^4.0.0" + protobufjs "~6.11.2" cross-spawn@^5.1.0: version "5.1.0" @@ -2081,7 +1900,7 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +cross-spawn@^7.0.0: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -2141,7 +1960,7 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: +debug@4, debug@^4.1.0, debug@^4.1.1: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== @@ -2190,7 +2009,7 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -2279,13 +2098,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - domexception@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" @@ -2298,7 +2110,7 @@ electron-to-chromium@^1.4.17: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.67.tgz#699e59d6959d05f87865e12b3055bbcf492bbbee" integrity sha512-A6a2jEPLueEDfb7kvh7/E94RKKnIb01qL+4I7RFxtajmo+G9F5Ei7HgY5PRbQ4RDrh6DGDW66P0hD5XI2nRAcg== -elliptic@^6.5.3: +elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -2357,11 +2169,6 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - escodegen@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" @@ -2374,126 +2181,12 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^8.3.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" - integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== - -eslint-plugin-prettier@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0" - integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint@^8.5.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.10.0.tgz#931be395eb60f900c01658b278e05b6dae47199d" - integrity sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw== - dependencies: - "@eslint/eslintrc" "^1.2.0" - "@humanwhocodes/config-array" "^0.9.2" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.3.1" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^6.0.1" - globals "^13.6.0" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -espree@^9.3.1: - version "9.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" - integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== - dependencies: - acorn "^8.7.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^3.3.0" - esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: +estraverse@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== @@ -2619,16 +2312,11 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: +fast-deep-equal@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - fast-glob@^3.2.9: version "3.2.11" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" @@ -2645,7 +2333,7 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -2664,13 +2352,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -2717,19 +2398,6 @@ find-yarn-workspace-root2@1.2.16: micromatch "^4.0.2" pkg-dir "^4.2.0" -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.2.5" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" - integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== - follow-redirects@^1.14.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" @@ -2817,11 +2485,6 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -2891,14 +2554,7 @@ glob-parent@^5.1.2: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -2915,13 +2571,6 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.6.0, globals@^13.9.0: - version "13.12.1" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb" - integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw== - dependencies: - type-fest "^0.20.2" - globalthis@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" @@ -3108,24 +2757,11 @@ ieee754@^1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.1.8, ignore@^5.2.0: +ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - import-local@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" @@ -3286,7 +2922,7 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -3826,13 +3462,6 @@ js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.6.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - jsdom@^16.4.0: version "16.7.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" @@ -3876,21 +3505,11 @@ json-parse-even-better-errors@^2.3.0: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - json-schema-traverse@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - json5@2.x, json5@^2.1.2: version "2.2.0" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" @@ -3898,11 +3517,6 @@ json5@2.x, json5@^2.1.2: dependencies: minimist "^1.2.5" -jsonc-parser@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22" - integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA== - jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -3963,14 +3577,6 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -3979,17 +3585,17 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -libsodium-wrappers@^0.7.6: - version "0.7.10" - resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz#13ced44cacb0fc44d6ac9ce67d725956089ce733" - integrity sha512-pO3F1Q9NPLB/MWIhehim42b/Fwb30JNScCNh8TcQ/kIc+qGLQch8ag8wb0keK3EP5kbGakk1H8Wwo7v+36rNQg== - dependencies: - libsodium "^0.7.0" +libsodium-sumo@^0.7.11: + version "0.7.11" + resolved "https://registry.yarnpkg.com/libsodium-sumo/-/libsodium-sumo-0.7.11.tgz#ab0389e2424fca5c1dc8c4fd394906190da88a11" + integrity sha512-bY+7ph7xpk51Ez2GbE10lXAQ5sJma6NghcIDaSPbM/G9elfrjLa0COHl/7P6Wb/JizQzl5UQontOOP1z0VwbLA== -libsodium@^0.7.0: - version "0.7.10" - resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.7.10.tgz#c2429a7e4c0836f879d701fec2c8a208af024159" - integrity sha512-eY+z7hDrDKxkAK+QKZVNv92A5KYkxfvIshtBJkmg5TSiCnYqZP3i9OO9whE79Pwgm4jGaoHgkM4ao/b9Cyu4zQ== +libsodium-wrappers-sumo@^0.7.11: + version "0.7.11" + resolved "https://registry.yarnpkg.com/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.11.tgz#d96329ee3c0e7ec7f5fcf4cdde16cc3a1ae91d82" + integrity sha512-DGypHOmJbB1nZn89KIfGOAkDgfv5N6SBGC3Qvmy/On0P0WD1JQvNRS/e3UL3aFF+xC0m+MYz5M+MnRnK2HMrKQ== + dependencies: + libsodium-sumo "^0.7.11" lines-and-columns@^1.1.6: version "1.2.4" @@ -4020,11 +3626,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - lodash.startcase@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.startcase/-/lodash.startcase-4.4.0.tgz#9436e34ed26093ed7ffae1936144350915d9add8" @@ -4055,11 +3656,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lunr@^2.3.9: - version "2.3.9" - resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" - integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== - make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -4101,11 +3697,6 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -marked@^4.0.10: - version "4.0.12" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.12.tgz#2262a4e6fd1afd2f13557726238b69a48b982f7d" - integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ== - meow@^6.0.0: version "6.1.1" resolved "https://registry.yarnpkg.com/meow/-/meow-6.1.1.tgz#1ad64c4b76b2a24dfb2f635fddcadf320d251467" @@ -4466,18 +4057,6 @@ optionator@^0.8.1: type-check "~0.3.2" word-wrap "~1.2.3" -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -4553,13 +4132,6 @@ pako@^2.0.2: resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - parse-json@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -4706,23 +4278,11 @@ preferred-pm@^3.0.0: path-exists "^4.0.0" which-pm "2.0.0" -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.1.tgz#d9485dd5e499daa6cb547023b87a6cf51bee37d6" @@ -4733,11 +4293,6 @@ prettier@^1.19.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== -prettier@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" - integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== - pretty-format@^26.0.0, pretty-format@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" @@ -4934,11 +4489,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -4976,11 +4526,6 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - resolve-from@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" @@ -5010,7 +4555,7 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -5149,15 +4694,6 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shiki@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.10.1.tgz#6f9a16205a823b56c072d0f1a0bcd0f2646bef14" - integrity sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng== - dependencies: - jsonc-parser "^3.0.0" - vscode-oniguruma "^1.6.1" - vscode-textmate "5.2.0" - signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -5423,11 +4959,6 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -5513,11 +5044,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - throat@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" @@ -5614,25 +5140,6 @@ ts-jest@^26.4.3: semver "7.x" yargs-parser "20.x" -ts-node@^10.4.0: - version "10.6.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.6.0.tgz#c3f4195d5173ce3affdc8f2fd2e9a7ac8de5376a" - integrity sha512-CJen6+dfOXolxudBQXnVjRVvYTmTWbyz7cn+xq2XTsvnaXbHqr4gXSCNbS2Jj8yTZMuGwUoBESLaOkLascVVvg== - dependencies: - "@cspotcode/source-map-support" "0.7.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.0" - yn "3.1.1" - ts-node@^8.3.0: version "8.10.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" @@ -5644,23 +5151,16 @@ ts-node@^8.3.0: source-map-support "^0.5.17" yn "3.1.1" -tslib@2.3.1, tslib@^2.3.1: +tslib@2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - tty-table@^2.8.10: version "2.8.13" resolved "https://registry.yarnpkg.com/tty-table/-/tty-table-2.8.13.tgz#d484a416381973eaebbdf19c79136b390e5c6d70" @@ -5680,13 +5180,6 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -5704,11 +5197,6 @@ type-fest@^0.13.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" @@ -5731,27 +5219,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typedoc@^0.22.10: - version "0.22.12" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.22.12.tgz#52a8bb0e77458dcbab35fb89e24b80160ba6558d" - integrity sha512-FcyC+YuaOpr3rB9QwA1IHOi9KnU2m50sPJW5vcNRPCIdecp+3bFkh7Rq5hBU1Fyn29UR2h4h/H7twZHWDhL0sw== - dependencies: - glob "^7.2.0" - lunr "^2.3.9" - marked "^4.0.10" - minimatch "^3.0.4" - shiki "^0.10.0" - typescript@4.3.5: version "4.3.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== -typescript@^4.4.4: - version "4.6.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" - integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== - union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -5815,16 +5287,6 @@ uuid@^8.3.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -v8-compile-cache-lib@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" - integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== - -v8-compile-cache@^2.0.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" - integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== - v8-to-istanbul@^7.0.0: version "7.1.2" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz#30898d1a7fa0c84d225a2c1434fb958f290883c1" @@ -5842,16 +5304,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -vscode-oniguruma@^1.6.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz#aeb9771a2f1dbfc9083c8a7fdd9cccaa3f386607" - integrity sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA== - -vscode-textmate@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" - integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== - w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -5958,7 +5410,7 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2 || 3 || 4" -word-wrap@^1.2.3, word-wrap@~1.2.3: +word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== From 847f1da0347b2142653db72faf6ef57b3063a5ed Mon Sep 17 00:00:00 2001 From: Calvin Wang Date: Wed, 2 Aug 2023 11:08:15 +1000 Subject: [PATCH 12/14] remove rdd requirements --- .../contracts/ocr2/inspection/inspect.ts | 56 ++++++++++++------- .../contracts/ocr2/inspection/responses.ts | 48 +++++++++++----- .../contracts/ocr2/proposal/acceptProposal.ts | 11 +++- .../commands/contracts/ocr2/proposeConfig.ts | 37 +++++++----- .../contracts/ocr2/proposeOffchainConfig.ts | 6 +- .../contracts/ownership/acceptOwnership.ts | 11 +++- .../contracts/ownership/transferOwnership.ts | 10 +++- .../proxy_ocr2/inspection/inspect.ts | 23 +++++--- 8 files changed, 136 insertions(+), 66 deletions(-) diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/inspect.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/inspect.ts index f6b23474..c0a41c98 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/inspect.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/inspect.ts @@ -29,30 +29,48 @@ type ContractExpectedInfo = { const makeInput = async (flags: any, args: string[]): Promise => { if (flags.input) return flags.input as ContractExpectedInfo - const rdd = RDD.getRDD(flags.rdd) - const contract = args[0] - const info = rdd.contracts[contract] - const aggregatorOperators: string[] = info.oracles.map((o) => o.operator) - const transmitters = aggregatorOperators.map((o) => rdd.operators[o].ocrNodeAddress[0]) - const billingAccessController = flags.billingAccessController || process.env.BILLING_ACCESS_CONTROLLER - const requesterAccessController = flags.requesterAccessController || process.env.REQUESTER_ACCESS_CONTROLLER - const link = flags.link || process.env.LINK - const { offchainConfig } = getSetConfigInputFromRDD(rdd, contract) + if (flags.rdd) { + const rdd = RDD.getRDD(flags.rdd) + const contract = args[0] + const info = rdd.contracts[contract] + const aggregatorOperators: string[] = info.oracles.map((o) => o.operator) + const transmitters = aggregatorOperators.map((o) => rdd.operators[o].ocrNodeAddress[0]) + const billingAccessController = flags.billingAccessController || process.env.BILLING_ACCESS_CONTROLLER + const requesterAccessController = flags.requesterAccessController || process.env.REQUESTER_ACCESS_CONTROLLER + const link = flags.link || process.env.LINK + + const { offchainConfig } = getSetConfigInputFromRDD(rdd, contract) + + return { + description: info.name, + decimals: info.decimals, + transmitters, + billingAccessController, + requesterAccessController, + link, + billing: { + observationPaymentGjuels: info.billing.observationPaymentGjuels, + recommendedGasPriceMicro: info.billing.recommendedGasPriceMicro, + transmissionPaymentGjuels: info.billing.transmissionPaymentGjuels, + }, + offchainConfig, + } + } return { - description: info.name, - decimals: info.decimals, - transmitters, - billingAccessController, - requesterAccessController, - link, + description: flags.name, + decimals: flags.decimals, + transmitters: flags.transmitters, + billingAccessController: flags.billingAccessController || process.env.BILLING_ACCESS_CONTROLLER, + requesterAccessController: flags.requesterAccessController || process.env.REQUESTER_ACCESS_CONTROLLER, + link: flags.link || process.env.LINK, billing: { - observationPaymentGjuels: info.billing.observationPaymentGjuels, - recommendedGasPriceMicro: info.billing.recommendedGasPriceMicro, - transmissionPaymentGjuels: info.billing.transmissionPaymentGjuels, + observationPaymentGjuels: flags.observationPaymentGjuels, + recommendedGasPriceMicro: flags.recommendedGasPriceMicro, + transmissionPaymentGjuels: flags.transmissionPaymentGjuels, }, - offchainConfig, + offchainConfig: {}, //TODO: is this required? } } diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/responses.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/responses.ts index 7f195f13..53cc380b 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/responses.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/inspection/responses.ts @@ -38,25 +38,45 @@ type NewTransmissionEventData = { const makeInput = async (flags: any, args: string[]): Promise => { if (flags.input) return flags.input as CommandInput - const rdd = RDD.getRDD(flags.rdd) - const operators = rdd.operators - const aggregatorProps = rdd.contracts[args[0]] - const oracles = aggregatorProps['oracles'] - const aggregatorOperators: string[] = oracles.map((o) => o.operator) - const transmitters = aggregatorOperators.map((o) => rdd.operators[o].ocrNodeAddress[0]) - - const aggregatorOracles = oracles.map((o) => { + + if (flags.rdd) { + const rdd = RDD.getRDD(flags.rdd) + const aggregatorProps = rdd.contracts[args[0]] + const oracles = aggregatorProps['oracles'] + const aggregatorOperators: string[] = oracles.map((o) => o.operator) + const transmitters = aggregatorOperators.map((o) => rdd.operators[o].ocrNodeAddress[0]) + + const aggregatorOracles = oracles.map((o) => { + return { + transmitter: rdd.operators[o.operator].ocrNodeAddress[0], + name: o.operator, + apis: o.api, + } + }) + + return { + transmitters, + description: aggregatorProps.name, + aggregatorOracles, + } + } + + if ((flags.operators.length != flags.apis.length) != flags.transmitters.length) { + throw Error("The number of operators, transmitters and apis don't match") + } + + const aggregatorOracles = flags.transmitters.map((transmitter, i) => { return { - transmitter: operators[o.operator].ocrNodeAddress[0], - name: o.operator, - apis: o.api, + transmitter, + name: flags.operators[i], + apis: flags.apis[i], } }) return { - transmitters, - description: aggregatorProps.name, - aggregatorOracles, + transmitters: flags.transmitters, + description: flags.name, + aggregatorOracles: aggregatorOracles, } } diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposal/acceptProposal.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposal/acceptProposal.ts index 09c2c6b0..57ba8f99 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposal/acceptProposal.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposal/acceptProposal.ts @@ -74,9 +74,14 @@ const makeCommandInput = async (flags: any, args: string[]): Promise => { if (flags.input) return flags.input as CommandInput - const { rdd: rddPath } = flags - - const rdd = RDD.getRDD(rddPath) - const contract = args[0] - const aggregator = rdd.contracts[contract] - const aggregatorOperators: any[] = aggregator.oracles.map((o) => rdd.operators[o.operator]) - const signers = aggregatorOperators.map((o) => o.ocr2OnchainPublicKey[0].replace('ocr2on_cosmos_', '')) - const transmitters = aggregatorOperators.map((o) => o.ocrNodeAddress[0]) - const payees = aggregatorOperators.map((o) => o.adminAddress) + if (flags.rdd) { + const { rdd: rddPath } = flags + const rdd = RDD.getRDD(rddPath) + const contract = args[0] + const aggregator = rdd.contracts[contract] + const aggregatorOperators: any[] = aggregator.oracles.map((o) => rdd.operators[o.operator]) + const signers = aggregatorOperators.map((o) => o.ocr2OnchainPublicKey[0].replace('ocr2on_cosmos_', '')) + const transmitters = aggregatorOperators.map((o) => o.ocrNodeAddress[0]) + const payees = aggregatorOperators.map((o) => o.adminAddress) + return { + f: aggregator.config.f, + proposalId: flags.proposalId || flags.configProposal || flags.id, // -configProposal alias requested by eng ops + signers, + transmitters, + payees, + onchainConfig: '', + } + } return { - f: aggregator.config.f, - proposalId: flags.proposalId || flags.configProposal || flags.id, // -configProposal alias requested by eng ops - signers, - transmitters, - payees, + f: parseInt(flags.f), + proposalId: flags.proposalId, + signers: flags.signers, + transmitters: flags.transmitters, + payees: flags.payees, onchainConfig: '', } } diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposeOffchainConfig.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposeOffchainConfig.ts index bcabfbce..7da5d9f8 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposeOffchainConfig.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ocr2/proposeOffchainConfig.ts @@ -26,7 +26,7 @@ export const getSetConfigInputFromRDD = ( const config = aggregator.config const aggregatorOperators: any[] = aggregator.oracles.map((o) => rdd.operators[o.operator]) - const operatorsPublicKeys = aggregatorOperators.map((o) => o.ocr2OffchainPublicKey[0].replace('ocr2off_cosmos_', '')) + const operatorsPublicKeys = aggregatorOperators.map((o) => o.ocr2OffchainPublicKey[0]) const operatorsPeerIds = aggregatorOperators.map((o) => o.peerId[0]) const operatorConfigPublicKeys = aggregatorOperators.map((o) => o.ocr2ConfigPublicKey[0]) @@ -89,7 +89,7 @@ const makeCommandInput = async (flags: any, args: string[]): Promise true const beforeExecute: BeforeExecute = (context) => async (signer) => { const currentOwner: AccAddress = await context.provider.queryContractSmart(context.contract, 'owner' as any) - const contract = RDD.getContractFromRDD(RDD.getRDD(context.flags.rdd), context.contract) - logger.info(`Accepting Ownership Transfer of contract of type "${contract.type}": - - Contract: ${logger.styleAddress(contract.address)} ${contract.description ? '- ' + contract.description : ''} + let contract: RDDContract | null = null + if (context.flags.rdd) { + contract = RDD.getContractFromRDD(RDD.getRDD(context.flags.rdd), context.contract) + } + + logger.info(`Accepting Ownership Transfer of contract" ${contract ? ' of type' + contract.type : ''}": + - Contract: ${logger.styleAddress(context.contract)} ${contract?.description ? '- ' + contract.description : ''} - Current Owner: ${logger.styleAddress(currentOwner)} - Next Owner (Current signer): ${logger.styleAddress(signer)} `) diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ownership/transferOwnership.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ownership/transferOwnership.ts index 26fa39ba..72a7c38f 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ownership/transferOwnership.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/ownership/transferOwnership.ts @@ -2,6 +2,7 @@ import { RDD, logger, AccAddress } from '@chainlink/gauntlet-cosmos' import { AbstractInstruction, BeforeExecute } from '../../abstract/executionWrapper' import { CATEGORIES } from '../../../lib/constants' import { CONTRACT_LIST } from '../../../lib/contracts' +import { RDDContract } from '@chainlink/gauntlet-cosmos/dist/lib/rdd' type CommandInput = { to: string @@ -33,9 +34,12 @@ const validateInput = (input: CommandInput): boolean => { const beforeExecute: BeforeExecute = (context, input) => async () => { const currentOwner = await context.provider.queryContractSmart(context.contract, 'owner' as any) - const contract = RDD.getContractFromRDD(RDD.getRDD(context.flags.rdd), context.contract) - logger.info(`Proposing Ownership Transfer of contract of type "${contract.type}": - - Contract: ${contract.address} ${contract.description ? '- ' + contract.description : ''} + let contract: RDDContract | null = null + if (context.flags.rdd) { + contract = RDD.getContractFromRDD(RDD.getRDD(context.flags.rdd), context.contract) + } + logger.info(`Proposing Ownership Transfer of contract" ${contract ? ' of type' + contract.type : ''}": + - Contract: ${context.contract} ${contract?.description ? '- ' + contract.description : ''} - Current Owner: ${currentOwner} - Next Owner: ${logger.styleAddress(input.contract.to)} `) diff --git a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/proxy_ocr2/inspection/inspect.ts b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/proxy_ocr2/inspection/inspect.ts index 685c285d..1f12d0cc 100644 --- a/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/proxy_ocr2/inspection/inspect.ts +++ b/packages-ts/gauntlet-cosmos-contracts/src/commands/contracts/proxy_ocr2/inspection/inspect.ts @@ -24,15 +24,24 @@ type ContractExpectedInfo = { const makeInput = async (flags: any, args: string[]): Promise => { if (flags.input) return flags.input as CommandInput - const rdd = RDD.getRDD(flags.rdd) - const contract = args[0] - const info = rdd.proxies[contract] - const decimals = rdd.contracts[rdd.proxies[contract].aggregator].decimals + + if (flags.rdd) { + const rdd = RDD.getRDD(flags.rdd) + const contract = args[0] + const info = rdd.proxies[contract] + const decimals = rdd.contracts[rdd.proxies[contract].aggregator].decimals + + return { + aggregator: info.aggregator, + description: info.name, + decimals, + } + } return { - aggregator: info.aggregator, - description: info.name, - decimals, + aggregator: args[0], + description: flags.description || '', + decimals: flags.decimals || '', } } From 13bfac80e3e39ea6fac1d432e62048f5b10ea154 Mon Sep 17 00:00:00 2001 From: Calvin Wang Date: Wed, 2 Aug 2023 13:28:33 +1000 Subject: [PATCH 13/14] bump optimizer and wasmd version --- scripts/build-contracts.sh | 2 +- scripts/wasmd.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build-contracts.sh b/scripts/build-contracts.sh index 28d1bd72..c5884da0 100755 --- a/scripts/build-contracts.sh +++ b/scripts/build-contracts.sh @@ -2,6 +2,6 @@ docker run --rm -v "$(pwd)":/code \ --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ - cosmwasm/workspace-optimizer:0.13.0 + cosmwasm/workspace-optimizer:0.14.0 # regenerate schemas for d in contracts/*/; do cd "$d"; cargo schema; cd ../..; done diff --git a/scripts/wasmd.sh b/scripts/wasmd.sh index c29fffb8..3b2d6b66 100755 --- a/scripts/wasmd.sh +++ b/scripts/wasmd.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash container_name="chainlink-cosmos.wasmd" -container_version="v0.30.0" +container_version="v0.40.1" genesis_account="wasm1lsagfzrm4gz28he4wunt63sts5xzmczwda8vl6" set -euo pipefail From 813c77b14bd3fe8447b05382a76cc92cb01c516f Mon Sep 17 00:00:00 2001 From: Calvin Wang Date: Wed, 2 Aug 2023 22:21:55 +1000 Subject: [PATCH 14/14] wip --- integration-tests/common/client.go | 16 +- integration-tests/common/common.go | 61 ++- integration-tests/common/test_common.go | 358 ++++++++++++++++++ integration-tests/gauntlet/gauntlet.go | 28 +- integration-tests/ocr2_test.go | 17 +- .../adapters/cosmwasm/contract_cache.go | 12 +- .../adapters/cosmwasm/contract_reader.go | 21 +- pkg/cosmos/adapters/cosmwasm/types.go | 7 +- 8 files changed, 441 insertions(+), 79 deletions(-) create mode 100644 integration-tests/common/test_common.go diff --git a/integration-tests/common/client.go b/integration-tests/common/client.go index 44971cab..671af67e 100644 --- a/integration-tests/common/client.go +++ b/integration-tests/common/client.go @@ -1,6 +1,8 @@ package common import ( + "fmt" + "github.com/smartcontractkit/chainlink-env/environment" "github.com/smartcontractkit/chainlink/integration-tests/client" ) @@ -18,10 +20,12 @@ func NewChainlinkClient(env *environment.Environment, chainName string, chainId if err != nil { return nil, err } + fmt.Println(nodes) nodeKeys, _, err := client.CreateNodeKeysBundle(nodes, chainName, chainId) if err != nil { return nil, err } + fmt.Println(nodeKeys) for _, n := range nodes { _, _, err = n.CreateCosmosChain(&client.CosmosChainAttributes{ ChainID: chainId, @@ -47,23 +51,23 @@ func NewChainlinkClient(env *environment.Environment, chainName string, chainId } func (cc *ChainlinkClient) LoadOCR2Config(accountAddresses []string) (*OCR2Config, error) { - var offChaiNKeys []string - var onChaiNKeys []string + var offChainKeys []string + var onChainKeys []string var peerIds []string var txKeys []string var cfgKeys []string for i, key := range cc.NodeKeys { - offChaiNKeys = append(offChaiNKeys, key.OCR2Key.Data.Attributes.OffChainPublicKey) + offChainKeys = append(offChainKeys, key.OCR2Key.Data.Attributes.OffChainPublicKey) peerIds = append(peerIds, key.PeerID) txKeys = append(txKeys, accountAddresses[i]) - onChaiNKeys = append(onChaiNKeys, key.OCR2Key.Data.Attributes.OnChainPublicKey) + onChainKeys = append(onChainKeys, key.OCR2Key.Data.Attributes.OnChainPublicKey) cfgKeys = append(cfgKeys, key.OCR2Key.Data.Attributes.ConfigPublicKey) } var payload = TestOCR2Config - payload.Signers = onChaiNKeys + payload.Signers = onChainKeys payload.Transmitters = txKeys - payload.OffchainConfig.OffchainPublicKeys = offChaiNKeys + payload.OffchainConfig.OffchainPublicKeys = offChainKeys payload.OffchainConfig.PeerIds = peerIds payload.OffchainConfig.ConfigPublicKeys = cfgKeys return &payload, nil diff --git a/integration-tests/common/common.go b/integration-tests/common/common.go index dd9de27c..f9855850 100644 --- a/integration-tests/common/common.go +++ b/integration-tests/common/common.go @@ -26,34 +26,19 @@ const ( ChainBlockTimeSoak = "2s" ) -var ( - observationSource = ` - val [type="bridge" name="bridge-coinmetrics" requestData=<{"data": {"from":"LINK","to":"USD"}}>] - parse [type="jsonparse" path="result"] - val -> parse - ` - juelsPerFeeCoinSource = `""" - sum [type="sum" values=<[451000]> ] - sum - """ - ` -) - type Common struct { - IsSoak bool - P2PPort string - ChainName string - ChainId string - NodeCount int - TTL time.Duration - NodeUrl string - Mnemonic string - Account string - ObservationSource string - JuelsPerFeeCoinSource string - ClConfig map[string]any - K8Config *environment.Config - Env *environment.Environment + IsSoak bool + P2PPort string + ChainName string + ChainId string + NodeCount int + TTL time.Duration + NodeUrl string + Mnemonic string + Account string + ClConfig map[string]any + K8Config *environment.Config + Env *environment.Environment } // getEnv gets the environment variable if it exists and sets it for the remote runner @@ -96,16 +81,14 @@ func getTTL() time.Duration { func NewCommon() *Common { c := &Common{ - IsSoak: getEnv("SOAK") != "", - ChainName: chainName, - ChainId: chainID, - NodeCount: getNodeCount(), - TTL: getTTL(), - NodeUrl: getEnv("NODE_URL"), - Mnemonic: getEnv("MNEMONIC"), - Account: getEnv("ACCOUNT"), - ObservationSource: observationSource, - JuelsPerFeeCoinSource: juelsPerFeeCoinSource, + IsSoak: getEnv("SOAK") != "", + ChainName: chainName, + ChainId: chainID, + NodeCount: getNodeCount(), + TTL: getTTL(), + NodeUrl: getEnv("NODE_URL"), + Mnemonic: getEnv("MNEMONIC"), + Account: getEnv("ACCOUNT"), } return c } @@ -146,9 +129,13 @@ ListenAddresses = ['0.0.0.0:6690'] "replicas": c.NodeCount, "toml": baseTOML, } + fmt.Println(c.ClConfig) + // replace this env with local docker c.Env = environment.New(c.K8Config). AddHelm(wasmd.New(nil)). AddHelm(mockservercfg.New(nil)). AddHelm(mockserver.New(nil)). AddHelm(chainlink.New(0, c.ClConfig)) + + fmt.Println(c.Env) } diff --git a/integration-tests/common/test_common.go b/integration-tests/common/test_common.go new file mode 100644 index 00000000..d15fbd32 --- /dev/null +++ b/integration-tests/common/test_common.go @@ -0,0 +1,358 @@ +package common + +import ( + "context" + "fmt" + "math/big" + "testing" + "time" + + cosmosSDK "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters/cosmwasm" + cosmosClient "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/client" + "github.com/smartcontractkit/chainlink-relay/pkg/logger" + "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/ocr2" + + // "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/starknet" + "github.com/smartcontractkit/chainlink/integration-tests/client" + + "github.com/smartcontractkit/chainlink-cosmos/ops/wasmd" + // "github.com/smartcontractkit/chainlink-starknet/ops" + "github.com/smartcontractkit/chainlink-cosmos/integration-tests/gauntlet" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + "github.com/smartcontractkit/chainlink-testing-framework/utils" + // "github.com/smartcontractkit/chainlink-starknet/integration-tests/utils" +) + +var ( + // These are one of the default addresses based on the seed we pass to devnet which is 0 + // defaultWalletPrivKey = ops.PrivateKeys0Seed[0] + defaultWalletAddress string // derived in init() + rpcRequestTimeout = time.Second * 300 + dumpPath = "/dumps/dump.pkl" + mockServerValue = 900000 +) + +var ( + observationSource = ` + val [type="bridge" name="bridge-coinmetrics" requestData=<{"data": {"from":"LINK","to":"USD"}}>] + parse [type="jsonparse" path="result"] + val -> parse + ` + juelsPerFeeCoinSource = `""" + sum [type="sum" values=<[451000]> ] + sum + """ + ` +) + +// func init() { +// // wallet contract derivation +// var keyBytes []byte +// keyBytes, err := hex.DecodeString(strings.TrimPrefix(defaultWalletPrivKey, "0x")) +// if err != nil { +// panic(err) +// } +// accountBytes, err := pubKeyToDevnetAccount(starkkey.Raw(keyBytes).Key().PublicKey()) +// if err != nil { +// panic(err) +// } +// defaultWalletAddress = "0x" + hex.EncodeToString(accountBytes) +// } + +type Test struct { + Devnet *wasmd.CosmosDevnetClient + Cc *ChainlinkClient + CosmosClient *cosmosClient.Client + OCR2Client *cosmwasm.OCR2Reader + Sg *gauntlet.StarknetGauntlet + mockServer *ctfClient.MockserverClient + Common *Common + AccountAddresses []string + LinkTokenAddr string + OCRAddr string + AccessControllerAddr string + ProxyAddr string + ObservationSource string + JuelsPerFeeCoinSource string + T *testing.T +} + +// DeployCluster Deploys and sets up config of the environment and nodes +func (testState *Test) DeployCluster() { + lggr := logger.Nop() + testState.Cc = &ChainlinkClient{} + testState.ObservationSource = testState.GetDefaultObservationSource() + testState.JuelsPerFeeCoinSource = testState.GetDefaultJuelsPerFeeCoinSource() + testState.DeployEnv() + testState.T.Log("deploy env success") + if testState.Common.Env.WillUseRemoteRunner() { + return // short circuit here if using a remote runner + } + testState.SetupClients() + if testState.Common.Testnet { + testState.Common.Env.URLs[testState.Common.ServiceKeyL2][1] = testState.Common.NodeUrl + } + var err error + testState.Cc.NKeys, testState.Cc.ChainlinkNodes, err = testState.Common.CreateKeys(testState.Common.Env) + require.NoError(testState.T, err, "Creating chains and keys should not fail") + testState.CosmosClient, err = cosmosClient.NewClient(testState.Common.ChainId, testState.Common.NodeUrl, lggr, &rpcRequestTimeout) + require.NoError(testState.T, err, "Creating starknet client should not fail") + testState.OCR2Client = cosmwasm.NewOCR2Reader(cosmosSDK.AccAddress(testState.OCRAddr), testState.CosmosClient, lggr) + // if !testState.Common.Testnet { + // err = os.Setenv("PRIVATE_KEY", testState.GetDefaultPrivateKey()) + // require.NoError(testState.T, err, "Setting private key should not fail") + // err = os.Setenv("ACCOUNT", testState.GetDefaultWalletAddress()) + // require.NoError(testState.T, err, "Setting account address should not fail") + // testState.Devnet.AutoDumpState() // Auto dumping devnet state to avoid losing contracts on crash + // } +} + +// DeployEnv Deploys the environment +func (testState *Test) DeployEnv() { + err := testState.Common.Env.Run() + require.NoError(testState.T, err) + if testState.Common.Env.WillUseRemoteRunner() { + return // short circuit here if using a remote runner + } + testState.mockServer, err = ctfClient.ConnectMockServer(testState.Common.Env) + require.NoError(testState.T, err, "Creating mockserver clients shouldn't fail") +} + +// SetupClients Sets up the starknet client +func (testState *Test) SetupClients() { + l := utils.GetTestLogger(testState.T) + if testState.Common.Testnet { + l.Debug().Msg(fmt.Sprintf("Overriding L2 RPC: %s", testState.Common.L2RPCUrl)) + } else { + testState.Common.L2RPCUrl = testState.Common.Env.URLs[testState.Common.ServiceKeyL2][0] // For local runs setting local ip + if testState.Common.Env.Cfg.InsideK8s { + testState.Common.L2RPCUrl = testState.Common.Env.URLs[testState.Common.ServiceKeyL2][1] // For remote runner setting remote IP + } + l.Debug().Msg(fmt.Sprintf("L2 RPC: %s", testState.Common.L2RPCUrl)) + testState.Devnet = testState.Devnet.NewStarknetDevnetClient(testState.Common.L2RPCUrl, dumpPath) + } +} + +// LoadOCR2Config Loads and returns the default starknet gauntlet config +// func (testState *Test) LoadOCR2Config() (*ops.OCR2Config, error) { +// var offChaiNKeys []string +// var onChaiNKeys []string +// var peerIds []string +// var txKeys []string +// var cfgKeys []string +// for i, key := range testState.Cc.NKeys { +// offChaiNKeys = append(offChaiNKeys, key.OCR2Key.Data.Attributes.OffChainPublicKey) +// peerIds = append(peerIds, key.PeerID) +// txKeys = append(txKeys, testState.AccountAddresses[i]) +// onChaiNKeys = append(onChaiNKeys, key.OCR2Key.Data.Attributes.OnChainPublicKey) +// cfgKeys = append(cfgKeys, key.OCR2Key.Data.Attributes.ConfigPublicKey) +// } + +// var payload = ops.TestOCR2Config +// payload.Signers = onChaiNKeys +// payload.Transmitters = txKeys +// payload.OffchainConfig.OffchainPublicKeys = offChaiNKeys +// payload.OffchainConfig.PeerIds = peerIds +// payload.OffchainConfig.ConfigPublicKeys = cfgKeys + +// return &payload, nil +// } + +func (testState *Test) SetUpNodes(mockServerVal int) { + testState.SetBridgeTypeAttrs(&client.BridgeTypeAttributes{ + Name: "bridge-mockserver", + URL: testState.GetMockServerURL(), + }) + err := testState.SetMockServerValue("", mockServerVal) + require.NoError(testState.T, err, "Setting mock server value should not fail") + err = testState.Common.CreateJobsForContract(testState.GetChainlinkClient(), testState.ObservationSource, testState.JuelsPerFeeCoinSource, testState.OCRAddr, testState.AccountAddresses) + require.NoError(testState.T, err, "Creating jobs should not fail") +} + +// GetStarknetAddress Returns the local StarkNET address +func (testState *Test) GetStarknetAddress() string { + return testState.Common.Env.URLs[testState.Common.ServiceKeyL2][0] +} + +// GetStarknetAddressRemote Returns the remote StarkNET address +func (testState *Test) GetStarknetAddressRemote() string { + return testState.Common.Env.URLs[testState.Common.ServiceKeyL2][1] +} + +// GetNodeKeys Returns the node key bundles +func (testState *Test) GetNodeKeys() []client.NodeKeysBundle { + return testState.Cc.NKeys +} + +func (testState *Test) GetChainlinkNodes() []*client.Chainlink { + return testState.Cc.ChainlinkNodes +} + +// func (testState *Test) GetDefaultPrivateKey() string { +// return defaultWalletPrivKey +// } + +func (testState *Test) GetDefaultWalletAddress() string { + return defaultWalletAddress +} + +func (testState *Test) GetChainlinkClient() *ChainlinkClient { + return testState.Cc +} + +func (testState *Test) GetCosmosDevnetClient() *wasmd.CosmosDevnetClient { + return testState.Devnet +} + +func (testState *Test) SetBridgeTypeAttrs(attr *client.BridgeTypeAttributes) { + testState.Cc.bTypeAttr = attr +} + +func (testState *Test) GetMockServerURL() string { + return testState.mockServer.Config.ClusterURL +} + +func (testState *Test) SetMockServerValue(path string, val int) error { + return testState.mockServer.SetValuePath(path, val) +} + +func (testState *Test) GetDefaultObservationSource() string { + return observationSource +} + +func (testState *Test) GetDefaultJuelsPerFeeCoinSource() string { + return juelsPerFeeCoinSource +} + +func (testState *Test) ValidateRounds(rounds int, isSoak bool) error { + l := utils.GetTestLogger(testState.T) + ctx := context.Background() // context background used because timeout handled by requestTimeout param + // assert new rounds are occurring + details := ocr2.TransmissionDetails{} + increasing := 0 // track number of increasing rounds + var stuck bool + stuckCount := 0 + var positive bool + + // validate balance in aggregator + // resLINK, errLINK := testState.Starknet.CallContract(ctx, starknet.CallOps{ + // ContractAddress: caigotypes.HexToHash(testState.LinkTokenAddr), + // Selector: "balance_of", + // Calldata: []string{caigotypes.HexToBN(testState.OCRAddr).String()}, + // }) + // require.NoError(testState.T, errLINK, "Reader balance from LINK contract should not fail") + // resAgg, errAgg := testState.Starknet.CallContract(ctx, starknet.CallOps{ + // ContractAddress: caigotypes.HexToHash(testState.OCRAddr), + // Selector: "link_available_for_payment", + // }) + // require.NoError(testState.T, errAgg, "Reader balance from LINK contract should not fail") + // balLINK, _ := new(big.Int).SetString(resLINK[0], 0) + // balAgg, _ := new(big.Int).SetString(resAgg[1], 0) + // isNegative, _ := new(big.Int).SetString(resAgg[0], 0) + // if isNegative.Sign() > 0 { + // balAgg = new(big.Int).Neg(balAgg) + // } + + // assert.Equal(testState.T, balLINK.Cmp(big.NewInt(0)), 1, "Aggregator should have non-zero balance") + // assert.GreaterOrEqual(testState.T, balLINK.Cmp(balAgg), 0, "Aggregator payment balance should be <= actual LINK balance") + + for start := time.Now(); time.Since(start) < testState.Common.TestDuration; { + l.Info().Msg(fmt.Sprintf("Elapsed time: %s, Round wait: %s ", time.Since(start), testState.Common.TestDuration)) + digest, epoch, round, latestAnswer, latestTimestamp, err := testState.OCR2Client.LatestTransmissionDetails(ctx, caigotypes.HexToHash(testState.OCRAddr)) + require.NoError(testState.T, err, "Failed to get latest transmission details") + // end condition: enough rounds have occurred + if !isSoak && increasing >= rounds && positive { + break + } + + // end condition: rounds have been stuck + if stuck && stuckCount > 50 { + l.Debug().Msg("failing to fetch transmissions means blockchain may have stopped") + break + } + + l.Info().Msg(fmt.Sprintf("Setting adapter value to %d", mockServerValue)) + err = testState.SetMockServerValue("", mockServerValue) + if err != nil { + l.Error().Msg(fmt.Sprintf("Setting mock server value error: %+v", err)) + } + // try to fetch rounds + time.Sleep(5 * time.Second) + + if err != nil { + l.Error().Msg(fmt.Sprintf("Transmission Error: %+v", err)) + continue + } + l.Info().Msg(fmt.Sprintf("Transmission Details: %+v", res)) + + // continue if no changes + if epoch == 0 && round == 0 { + continue + } + + ansCmp := latestAnswer.Cmp(big.NewInt(0)) + positive = ansCmp == 1 || positive + + // if changes from zero values set (should only initially) + if epoch > 0 && details.Epoch == 0 { + if !isSoak { + assert.Greater(testState.T, epoch, details.Epoch) + assert.GreaterOrEqual(testState.T, round, details.Round) + assert.NotEqual(testState.T, ansCmp, 0) // assert changed from 0 + assert.NotEqual(testState.T, digest, details.Digest) + assert.Equal(testState.T, details.LatestTimestamp.Before(latestTimestamp), true) + } + details = res + continue + } + // check increasing rounds + if !isSoak { + assert.Equal(testState.T, res.Digest, details.Digest, "Config digest should not change") + } else { + if res.Digest != details.Digest { + l.Error().Msg(fmt.Sprintf("Config digest should not change, expected %s got %s", details.Digest, res.Digest)) + } + } + if (res.Epoch > details.Epoch || (res.Epoch == details.Epoch && res.Round > details.Round)) && details.LatestTimestamp.Before(res.LatestTimestamp) { + increasing++ + stuck = false + stuckCount = 0 // reset counter + continue + } + + // reach this point, answer has not changed + stuckCount++ + if stuckCount > 30 { + stuck = true + increasing = 0 + } + } + if !isSoak { + assert.GreaterOrEqual(testState.T, increasing, rounds, "Round + epochs should be increasing") + assert.Equal(testState.T, positive, true, "Positive value should have been submitted") + assert.Equal(testState.T, stuck, false, "Round + epochs should not be stuck") + } + + // Test proxy reading + // TODO: would be good to test proxy switching underlying feeds + // roundDataRaw, err := testState.Starknet.CallContract(ctx, starknet.CallOps{ + // ContractAddress: caigotypes.HexToHash(testState.ProxyAddr), + // Selector: "latest_round_data", + // }) + // if !isSoak { + // require.NoError(testState.T, err, "Reading round data from proxy should not fail") + // assert.Equal(testState.T, len(roundDataRaw), 5, "Round data from proxy should match expected size") + // } + // valueBig, err := starknet.HexToUnsignedBig(roundDataRaw[1]) + // require.NoError(testState.T, err) + // value := valueBig.Int64() + // if value < 0 { + // assert.Equal(testState.T, value, int64(mockServerValue), "Reading from proxy should return correct value") + // } + + return nil +} diff --git a/integration-tests/gauntlet/gauntlet.go b/integration-tests/gauntlet/gauntlet.go index 70ff3f20..880b38e3 100644 --- a/integration-tests/gauntlet/gauntlet.go +++ b/integration-tests/gauntlet/gauntlet.go @@ -23,20 +23,23 @@ type CosmosGauntlet struct { type GauntletResponse struct { Responses []struct { Tx struct { - Hash string `json:"hash"` - Address string `json:"address"` - Status string `json:"status"` - CodeId int `json:"codeId"` - - Tx struct { - Address string `json:"address"` - Code string `json:"code"` - Result []string `json:"result"` - TransactionHash string `json:"transaction_hash"` - } `json:"tx"` + Logs interface{} `json:"logs"` + Height int `json:"height"` + TransactionHash string `json:"transactionHash"` + Events []struct { + Type string `json:"type"` + Attributes []struct { + Key string `json:"key"` + Value string `json:"value"` + } `json:"attributes"` + } `json:"events"` + GasWanted int `json:"gasWanted"` + GasUsed int `json:"gasUsed"` + CodeId int `json:"codeId"` // only present in upload commands } `json:"tx"` Contract string `json:"contract"` } `json:"responses"` + Data map[string]interface{} `json:"data"` } // NewCosmosGauntlet Creates a default gauntlet config @@ -214,8 +217,7 @@ func (cg *CosmosGauntlet) BeginProposal(ocrAddress string) (string, error) { if err != nil { return "", err } - // TODO: return proposal id - return cg.gr.Responses[0].Contract, nil + return cg.gr.Data["proposalId"].(string), nil } func (cg *CosmosGauntlet) ProposeOffchainConfig(proposalId string, cfg string, ocrAddress string) (string, error) { diff --git a/integration-tests/ocr2_test.go b/integration-tests/ocr2_test.go index bf79fabf..75a7e71a 100644 --- a/integration-tests/ocr2_test.go +++ b/integration-tests/ocr2_test.go @@ -18,8 +18,19 @@ import ( func TestOCRBasic(t *testing.T) { // Set up test logger := common.GetTestLogger(t) - commonConfig := common.NewCommon() - + t.Common := common.NewCommon() + t.Common.SetDefaultEnvironment(t) + t.Log(commonConfig.Env) + t.Log(commonConfig.Env.ChainlinkNodeDetails) + + // Set up CL nodes + t.DeployCluster() + require.NoError(t, err, "Deploying cluster should not fail") + if testState.Common.Env.WillUseRemoteRunner() { + return // short circuit here if using a remote runner + } + + // Set up gauntlet gauntletWorkingDir := fmt.Sprintf("%s/", utils.ProjectRoot) logger.Info().Str("working dir", gauntletWorkingDir).Msg("Initializing gauntlet") @@ -32,8 +43,6 @@ func TestOCRBasic(t *testing.T) { err = cg.SetupNetwork(commonConfig.NodeUrl, commonConfig.Mnemonic) require.NoError(t, err, "Setting up gauntlet network should not fail") - commonConfig.SetDefaultEnvironment(t) - // TODO: fund nodes if necessary // Upload contracts diff --git a/pkg/cosmos/adapters/cosmwasm/contract_cache.go b/pkg/cosmos/adapters/cosmwasm/contract_cache.go index f86d688d..916defb8 100644 --- a/pkg/cosmos/adapters/cosmwasm/contract_cache.go +++ b/pkg/cosmos/adapters/cosmwasm/contract_cache.go @@ -129,18 +129,18 @@ func (cc *ContractCache) updateConfig(ctx context.Context) error { } func (cc *ContractCache) updateTransmission(ctx context.Context) error { - digest, epoch, round, latestAnswer, latestTimestamp, err := cc.reader.LatestTransmissionDetails(ctx) + res, err := cc.reader.LatestTransmissionDetails(ctx) if err != nil { return fmt.Errorf("fetch latest transmission: %w", err) } now := time.Now() cc.transMu.Lock() cc.transTS = now - cc.digest = digest - cc.epoch = epoch - cc.round = round - cc.latestAnswer = latestAnswer - cc.latestTimestamp = latestTimestamp + cc.digest = res.LatestConfigDigest + cc.epoch = res.Epoch + cc.round = res.Round + cc.latestAnswer = res.LatestAnswer + cc.latestTimestamp = res.LatestTimestamp cc.transMu.Unlock() cc.lggr.Infof("updated transmission details. [epoch %v, round %v, answer %v, ts %v]", epoch, round, latestAnswer, latestTimestamp) diff --git a/pkg/cosmos/adapters/cosmwasm/contract_reader.go b/pkg/cosmos/adapters/cosmwasm/contract_reader.go index aec1707c..1172e836 100644 --- a/pkg/cosmos/adapters/cosmwasm/contract_reader.go +++ b/pkg/cosmos/adapters/cosmwasm/contract_reader.go @@ -8,7 +8,6 @@ import ( "math/big" "strconv" "strings" - "time" cosmosSDK "github.com/cosmos/cosmos-sdk/types" @@ -219,11 +218,7 @@ func (e ErrAttrDupe) Error() string { // LatestTransmissionDetails fetches the latest transmission details from address state func (r *OCR2Reader) LatestTransmissionDetails(ctx context.Context) ( - configDigest types.ConfigDigest, - epoch uint32, - round uint8, - latestAnswer *big.Int, - latestTimestamp time.Time, + transmissionDetails LatestTransmissionDetails, err error, ) { resp, err := r.chainReader.ContractState(r.address, []byte(`"latest_transmission_details"`)) @@ -242,28 +237,32 @@ func (r *OCR2Reader) LatestTransmissionDetails(ctx context.Context) ( if epoch != 0 { r.lggr.Errorf("unexpected non-zero epoch %v and no transmissions found contract %v", epoch, r.address) } - return digest, epoch, 0, big.NewInt(0), time.Unix(0, 0), nil + return LatestTransmissionDetails{ + LatestConfigDigest: digest, + Epoch: epoch, + }, nil } r.lggr.Errorf("error reading latest config digest and epoch err %v contract %v", err2, r.address) } // default response if there actually is an error - return types.ConfigDigest{}, 0, 0, big.NewInt(0), time.Now(), err + return LatestTransmissionDetails{}, err } // unmarshal var details LatestTransmissionDetails if err := json.Unmarshal(resp, &details); err != nil { - return types.ConfigDigest{}, 0, 0, big.NewInt(0), time.Now(), err + return LatestTransmissionDetails{}, err } // set answer big int ans := new(big.Int) if _, success := ans.SetString(details.LatestAnswer, 10); !success { - return types.ConfigDigest{}, 0, 0, big.NewInt(0), time.Now(), fmt.Errorf("Could not create *big.Int from %s", details.LatestAnswer) + return LatestTransmissionDetails{}, fmt.Errorf("Could not create *big.Int from %s", details.LatestAnswer) } + details.LatestAnswer = ans - return details.LatestConfigDigest, details.Epoch, details.Round, ans, time.Unix(details.LatestTimestamp, 0), nil + return details, nil } // LatestRoundRequested fetches the latest round requested by filtering event logs diff --git a/pkg/cosmos/adapters/cosmwasm/types.go b/pkg/cosmos/adapters/cosmwasm/types.go index 36844fd7..7d86d095 100644 --- a/pkg/cosmos/adapters/cosmwasm/types.go +++ b/pkg/cosmos/adapters/cosmwasm/types.go @@ -1,6 +1,9 @@ package cosmwasm import ( + "math/big" + "time" + "github.com/smartcontractkit/libocr/offchainreporting2/types" ) @@ -23,8 +26,8 @@ type LatestTransmissionDetails struct { LatestConfigDigest types.ConfigDigest `json:"latest_config_digest"` Epoch uint32 `json:"epoch"` Round uint8 `json:"round"` - LatestAnswer string `json:"latest_answer"` - LatestTimestamp int64 `json:"latest_timestamp"` + LatestAnswer *big.Int `json:"latest_answer"` + LatestTimestamp time.Time `json:"latest_timestamp"` } type LatestConfigDigestAndEpoch struct {