From 6e024f838a4c9f87a2dfd9834048501db40624c2 Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:14:03 -0700 Subject: [PATCH] Ccip-3535 env abstraction updated (#14598) * env changes * changes * lint * jd changes * fix typo --------- Co-authored-by: Connor Stein updates change --- .../deployment/ccip/add_chain_test.go | 8 +- .../deployment/ccip/add_lane_test.go | 2 +- .../ccip/changeset/2_initial_deploy_test.go | 6 +- .../deployment/ccip/test_helpers.go | 130 ++-- .../deployment/devenv/build_env.go | 33 +- integration-tests/deployment/devenv/don.go | 73 ++- .../deployment/devenv/environment.go | 16 +- integration-tests/deployment/devenv/jd.go | 44 +- integration-tests/deployment/helpers.go | 3 + .../deployment/memory/environment.go | 17 - .../deployment/memory/job_client.go | 9 + integration-tests/deployment/multiclient.go | 121 +++- integration-tests/smoke/ccip_test.go | 78 +-- integration-tests/web/sdk/client/client.go | 64 +- .../web/sdk/internal/generated/generated.go | 555 +++++++++++++++++- .../web/sdk/internal/genqlient.graphql | 40 +- 16 files changed, 1006 insertions(+), 193 deletions(-) diff --git a/integration-tests/deployment/ccip/add_chain_test.go b/integration-tests/deployment/ccip/add_chain_test.go index dbe86b85368..fc39bddcd93 100644 --- a/integration-tests/deployment/ccip/add_chain_test.go +++ b/integration-tests/deployment/ccip/add_chain_test.go @@ -24,8 +24,7 @@ import ( func TestAddChainInbound(t *testing.T) { // 4 chains where the 4th is added after initial deployment. - e := NewEnvironmentWithCRAndJobs(t, logger.TestLogger(t), 4) - require.Equal(t, len(e.Nodes), 5) + e := NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), 4) state, err := LoadOnchainState(e.Env, e.Ab) require.NoError(t, err) // Take first non-home chain as the new chain. @@ -127,6 +126,9 @@ func TestAddChainInbound(t *testing.T) { ExecuteProposal(t, e.Env, chainInboundExec, state, sel) } + replayBlocks, err := LatestBlocksByChain(testcontext.Get(t), e.Env.Chains) + require.NoError(t, err) + // Now configure the new chain using deployer key (not transferred to timelock yet). var offRampEnables []offramp.OffRampSourceChainConfigArgs for _, source := range initialDeploy { @@ -167,7 +169,7 @@ func TestAddChainInbound(t *testing.T) { } // Ensure job related logs are up to date. time.Sleep(30 * time.Second) - require.NoError(t, ReplayAllLogs(e.Nodes, e.Env.Chains)) + ReplayLogs(t, e.Env.Offchain, replayBlocks) // TODO: Send via all inbound lanes and use parallel helper // Now that the proposal has been executed we expect to be able to send traffic to this new 4th chain. diff --git a/integration-tests/deployment/ccip/add_lane_test.go b/integration-tests/deployment/ccip/add_lane_test.go index 3da74ec11a8..540b5dded54 100644 --- a/integration-tests/deployment/ccip/add_lane_test.go +++ b/integration-tests/deployment/ccip/add_lane_test.go @@ -16,7 +16,7 @@ func TestAddLane(t *testing.T) { // TODO: The offchain code doesn't yet support partial lane // enablement, need to address then re-enable this test. t.Skip() - e := NewEnvironmentWithCRAndJobs(t, logger.TestLogger(t), 3) + e := NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), 3) // Here we have CR + nodes set up, but no CCIP contracts deployed. state, err := LoadOnchainState(e.Env, e.Ab) require.NoError(t, err) diff --git a/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go b/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go index 8dc363b0cbb..5744dfbea95 100644 --- a/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go +++ b/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go @@ -20,10 +20,8 @@ import ( func Test0002_InitialDeploy(t *testing.T) { lggr := logger.TestLogger(t) ctx := ccdeploy.Context(t) - tenv := ccdeploy.NewEnvironmentWithCRAndFeeds(t, lggr, 3) + tenv := ccdeploy.NewMemoryEnvironment(t, lggr, 3) e := tenv.Env - nodes := tenv.Nodes - chains := e.Chains state, err := ccdeploy.LoadOnchainState(tenv.Env, tenv.Ab) require.NoError(t, err) @@ -52,7 +50,7 @@ func Test0002_InitialDeploy(t *testing.T) { require.NoError(t, err) // Ensure capreg logs are up to date. - require.NoError(t, ccdeploy.ReplayAllLogs(nodes, chains)) + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) // Apply the jobs. for nodeID, jobs := range output.JobSpecs { diff --git a/integration-tests/deployment/ccip/test_helpers.go b/integration-tests/deployment/ccip/test_helpers.go index c306ba4fd6a..59eecae4f29 100644 --- a/integration-tests/deployment/ccip/test_helpers.go +++ b/integration-tests/deployment/ccip/test_helpers.go @@ -9,6 +9,7 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/pkg/errors" "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" @@ -64,11 +65,39 @@ type DeployedEnv struct { Env deployment.Environment HomeChainSel uint64 FeedChainSel uint64 + ReplayBlocks map[uint64]uint64 } -type DeployedTestEnvironment struct { - DeployedEnv - Nodes map[string]memory.Node +func (e *DeployedEnv) SetupJobs(t *testing.T) { + ctx := testcontext.Get(t) + jbs, err := NewCCIPJobSpecs(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) + for nodeID, jobs := range jbs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Env.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + // Wait for plugins to register filters? + // TODO: Investigate how to avoid. + time.Sleep(30 * time.Second) + ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) +} + +func ReplayLogs(t *testing.T, oc deployment.OffchainClient, replayBlocks map[uint64]uint64) { + switch oc := oc.(type) { + case *memory.JobClient: + require.NoError(t, oc.ReplayLogs(replayBlocks)) + case *devenv.JobDistributor: + require.NoError(t, oc.ReplayLogs(replayBlocks)) + default: + t.Fatalf("unsupported offchain client type %T", oc) + } } func SetUpHomeAndFeedChains(t *testing.T, lggr logger.Logger, homeChainSel, feedChainSel uint64, chains map[uint64]deployment.Chain) (deployment.AddressBook, deployment.CapabilityRegistryConfig) { @@ -85,11 +114,24 @@ func SetUpHomeAndFeedChains(t *testing.T, lggr logger.Logger, homeChainSel, feed } } -// NewEnvironmentWithCRAndFeeds creates a new CCIP environment +func LatestBlocksByChain(ctx context.Context, chains map[uint64]deployment.Chain) (map[uint64]uint64, error) { + latestBlocks := make(map[uint64]uint64) + for _, chain := range chains { + latesthdr, err := chain.Client.HeaderByNumber(ctx, nil) + if err != nil { + return nil, errors.Wrapf(err, "failed to get latest header for chain %d", chain.Selector) + } + block := latesthdr.Number.Uint64() + latestBlocks[chain.Selector] = block + } + return latestBlocks, nil +} + +// NewMemoryEnvironment creates a new CCIP environment // with capreg, feeds and nodes set up. -func NewEnvironmentWithCRAndFeeds(t *testing.T, lggr logger.Logger, numChains int) DeployedTestEnvironment { +func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, numChains int) DeployedEnv { require.GreaterOrEqual(t, numChains, 2, "numChains must be at least 2 for home and feed chains") - ctx := Context(t) + ctx := testcontext.Get(t) chains := memory.NewMemoryChains(t, numChains) // Lower chainSel is home chain. var chainSels []uint64 @@ -103,6 +145,8 @@ func NewEnvironmentWithCRAndFeeds(t *testing.T, lggr logger.Logger, numChains in // Take lowest for determinism. homeChainSel := chainSels[HomeChainIndex] feedSel := chainSels[FeedChainIndex] + replayBlocks, err := LatestBlocksByChain(ctx, chains) + require.NoError(t, err) ab, capReg := SetUpHomeAndFeedChains(t, lggr, homeChainSel, feedSel, chains) nodes := memory.NewNodes(t, zapcore.InfoLevel, chains, 4, 1, capReg) @@ -114,55 +158,21 @@ func NewEnvironmentWithCRAndFeeds(t *testing.T, lggr logger.Logger, numChains in } e := memory.NewMemoryEnvironmentFromChainsNodes(t, lggr, chains, nodes) - return DeployedTestEnvironment{ - DeployedEnv: DeployedEnv{ - Ab: ab, - Env: e, - HomeChainSel: homeChainSel, - FeedChainSel: feedSel, - }, - Nodes: nodes, + return DeployedEnv{ + Ab: ab, + Env: e, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + ReplayBlocks: replayBlocks, } } -func NewEnvironmentWithCRAndJobs(t *testing.T, lggr logger.Logger, numChains int) DeployedTestEnvironment { - ctx := Context(t) - e := NewEnvironmentWithCRAndFeeds(t, lggr, numChains) - jbs, err := NewCCIPJobSpecs(e.Env.NodeIDs, e.Env.Offchain) - require.NoError(t, err) - for nodeID, jobs := range jbs { - for _, job := range jobs { - // Note these auto-accept - _, err := e.Env.Offchain.ProposeJob(ctx, - &jobv1.ProposeJobRequest{ - NodeId: nodeID, - Spec: job, - }) - require.NoError(t, err) - } - } - // Wait for plugins to register filters? - // TODO: Investigate how to avoid. - time.Sleep(30 * time.Second) - - // Ensure job related logs are up to date. - require.NoError(t, ReplayAllLogs(e.Nodes, e.Env.Chains)) +func NewMemoryEnvironmentWithJobs(t *testing.T, lggr logger.Logger, numChains int) DeployedEnv { + e := NewMemoryEnvironment(t, lggr, numChains) + e.SetupJobs(t) return e } -func ReplayAllLogs(nodes map[string]memory.Node, chains map[uint64]deployment.Chain) error { - blockBySel := make(map[uint64]uint64) - for sel := range chains { - blockBySel[sel] = 1 - } - for _, node := range nodes { - if err := node.ReplayLogs(blockBySel); err != nil { - return err - } - } - return nil -} - func SendRequest(t *testing.T, e deployment.Environment, state CCIPOnChainState, src, dest uint64, testRouter bool) uint64 { msg := router.ClientEVM2AnyMessage{ Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), @@ -228,8 +238,8 @@ func (d DeployedLocalDevEnvironment) RestartChainlinkNodes(t *testing.T) error { return errGrp.Wait() } -func NewDeployedLocalDevEnvironment(t *testing.T, lggr logger.Logger) DeployedLocalDevEnvironment { - ctx := Context(t) +func NewLocalDevEnvironment(t *testing.T, lggr logger.Logger) DeployedEnv { + ctx := testcontext.Get(t) // create a local docker environment with simulated chains and job-distributor // we cannot create the chainlink nodes yet as we need to deploy the capability registry first envConfig, testEnv, cfg := devenv.CreateDockerEnv(t) @@ -243,6 +253,8 @@ func NewDeployedLocalDevEnvironment(t *testing.T, lggr logger.Logger) DeployedLo require.NotEmpty(t, homeChainSel, "homeChainSel should not be empty") feedSel := envConfig.FeedChainSelector require.NotEmpty(t, feedSel, "feedSel should not be empty") + replayBlocks, err := LatestBlocksByChain(ctx, chains) + require.NoError(t, err) ab, capReg := SetUpHomeAndFeedChains(t, lggr, homeChainSel, feedSel, chains) // start the chainlink nodes with the CR address @@ -252,20 +264,16 @@ func NewDeployedLocalDevEnvironment(t *testing.T, lggr logger.Logger) DeployedLo e, don, err := devenv.NewEnvironment(ctx, lggr, *envConfig) require.NoError(t, err) require.NotNil(t, e) - require.NotNil(t, don) zeroLogLggr := logging.GetTestLogger(t) // fund the nodes devenv.FundNodes(t, zeroLogLggr, testEnv, cfg, don.PluginNodes()) - return DeployedLocalDevEnvironment{ - DeployedEnv: DeployedEnv{ - Ab: ab, - Env: *e, - HomeChainSel: homeChainSel, - FeedChainSel: feedSel, - }, - DON: don, - testEnv: testEnv, + return DeployedEnv{ + Ab: ab, + Env: *e, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + ReplayBlocks: replayBlocks, } } diff --git a/integration-tests/deployment/devenv/build_env.go b/integration-tests/deployment/devenv/build_env.go index 7b97a53e992..253c05f9863 100644 --- a/integration-tests/deployment/devenv/build_env.go +++ b/integration-tests/deployment/devenv/build_env.go @@ -9,10 +9,15 @@ import ( "github.com/AlekSi/pointer" "github.com/ethereum/go-ethereum/common" + + "github.com/pkg/errors" "github.com/rs/zerolog" chainselectors "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/require" "github.com/subosito/gotenv" + "golang.org/x/sync/errgroup" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" "github.com/smartcontractkit/chainlink-testing-framework/seth" @@ -205,7 +210,10 @@ func StartChainlinkNodes( InternalIP: n.API.InternalIP(), } } - envConfig.nodeInfo = nodeInfo + if envConfig == nil { + envConfig = &EnvironmentConfig{} + } + envConfig.JDConfig.nodeInfo = nodeInfo return nil } @@ -341,3 +349,26 @@ func CreateChainConfigFromNetworks( } return chains } + +// RestartChainlinkNodes restarts the chainlink nodes in the test environment +func RestartChainlinkNodes(t *testing.T, env *test_env.CLClusterTestEnv) error { + errGrp := errgroup.Group{} + if env == nil || env.ClCluster == nil { + return errors.Wrap(errors.New("no testenv or clcluster found "), "error restarting node") + } + for _, n := range env.ClCluster.Nodes { + n := n + errGrp.Go(func() error { + if err := n.Container.Terminate(testcontext.Get(t)); err != nil { + return err + } + err := n.RestartContainer() + if err != nil { + return err + } + return nil + }) + + } + return errGrp.Wait() +} diff --git a/integration-tests/deployment/devenv/don.go b/integration-tests/deployment/devenv/don.go index 9478b729f29..0b10bd091a8 100644 --- a/integration-tests/deployment/devenv/don.go +++ b/integration-tests/deployment/devenv/don.go @@ -5,10 +5,12 @@ import ( "fmt" "strconv" "strings" + "time" "github.com/AlekSi/pointer" "github.com/hashicorp/go-multierror" "github.com/rs/zerolog" + "github.com/sethvargo/go-retry" chainsel "github.com/smartcontractkit/chain-selectors" clclient "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -160,7 +162,7 @@ type Node struct { // It expects bootstrap nodes to have label with key "type" and value as "bootstrap". // It fetches the account address, peer id, and OCR2 key bundle id and creates the JobDistributorChainConfig. func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []ChainConfig, jd JobDistributor) error { - for _, chain := range chains { + for i, chain := range chains { chainId := strconv.FormatUint(chain.ChainID, 10) accountAddr, err := n.gqlClient.FetchAccountAddress(ctx, chainId) if err != nil { @@ -198,10 +200,11 @@ func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []ChainC } // JD silently fails to update nodeChainConfig. Therefore, we fetch the node config and // if it's not updated , we retry creating the chain config. - // as a workaround, we keep trying creating the chain config for 3 times until it's created + // as a workaround, we keep trying creating the chain config for 5 times until it's created retryCount := 1 - for retryCount < 3 { - err = n.gqlClient.CreateJobDistributorChainConfig(ctx, client.JobDistributorChainConfigInput{ + created := false + for retryCount < 5 { + chainConfigId, err := n.gqlClient.CreateJobDistributorChainConfig(ctx, client.JobDistributorChainConfigInput{ JobDistributorID: n.JDId, ChainID: chainId, ChainType: chain.ChainType, @@ -217,30 +220,66 @@ func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []ChainC if err != nil { return fmt.Errorf("failed to create CCIPOCR2SupportedChains for node %s: %w", n.Name, err) } - - nodeChainConfigs, err := jd.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{ - Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ - NodeIds: []string{n.NodeId}, - }}) - if err != nil { - return fmt.Errorf("failed to list node chain configs for node %s: %w", n.Name, err) - } - if nodeChainConfigs != nil && len(nodeChainConfigs.ChainConfigs) > 0 { + // JD doesn't update the node chain config immediately, so we need to wait for it to be updated + err = retry.Do(ctx, retry.WithMaxRetries(3, retry.NewFibonacci(1*time.Second)), func(ctx context.Context) error { + nodeChainConfigs, err := jd.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{ + Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ + NodeIds: []string{n.NodeId}, + }}) + if err != nil { + return fmt.Errorf("failed to list node chain configs for node %s: %w", n.Name, err) + } + if nodeChainConfigs != nil && len(nodeChainConfigs.ChainConfigs) == i+1 { + return nil + } + return fmt.Errorf("node chain config not updated properly") + }) + if err == nil { + created = true break } + // delete the node chain config if it's not updated properly and retry + err = n.gqlClient.DeleteJobDistributorChainConfig(ctx, chainConfigId) + if err != nil { + return fmt.Errorf("failed to delete job distributor chain config for node %s: %w", n.Name, err) + } + retryCount++ } + if !created { + return fmt.Errorf("failed to create CCIPOCR2SupportedChains for node %s", n.Name) + } } return nil } -func (n *Node) AcceptJob(ctx context.Context, id string) error { - spec, err := n.gqlClient.ApproveJobProposalSpec(ctx, id, false) +// AcceptJob accepts the job proposal for the given job proposal spec +func (n *Node) AcceptJob(ctx context.Context, spec string) error { + // fetch JD to get the job proposals + jd, err := n.gqlClient.GetJobDistributor(ctx, n.JDId) + if err != nil { + return err + } + if jd.GetJobProposals() == nil { + return fmt.Errorf("no job proposals found for node %s", n.Name) + } + // locate the job proposal id for the given job spec + var idToAccept string + for _, jp := range jd.JobProposals { + if jp.LatestSpec.Definition == spec { + idToAccept = jp.Id + break + } + } + if idToAccept == "" { + return fmt.Errorf("no job proposal found for job spec %s", spec) + } + approvedSpec, err := n.gqlClient.ApproveJobProposalSpec(ctx, idToAccept, false) if err != nil { return err } - if spec == nil { - return fmt.Errorf("no job proposal spec found for job id %s", id) + if approvedSpec == nil { + return fmt.Errorf("no job proposal spec found for job id %s", idToAccept) } return nil } diff --git a/integration-tests/deployment/devenv/environment.go b/integration-tests/deployment/devenv/environment.go index 74cde258cc3..e06b69769f8 100644 --- a/integration-tests/deployment/devenv/environment.go +++ b/integration-tests/deployment/devenv/environment.go @@ -17,7 +17,6 @@ type EnvironmentConfig struct { Chains []ChainConfig HomeChainSelector uint64 FeedChainSelector uint64 - nodeInfo []NodeInfo JDConfig JDConfig } @@ -26,25 +25,24 @@ func NewEnvironment(ctx context.Context, lggr logger.Logger, config EnvironmentC if err != nil { return nil, nil, fmt.Errorf("failed to create chains: %w", err) } - offChain, err := NewJDClient(config.JDConfig) + offChain, err := NewJDClient(ctx, config.JDConfig) if err != nil { return nil, nil, fmt.Errorf("failed to create JD client: %w", err) } - jd, ok := offChain.(JobDistributor) + jd, ok := offChain.(*JobDistributor) if !ok { return nil, nil, fmt.Errorf("offchain client does not implement JobDistributor") } - don, err := NewRegisteredDON(ctx, config.nodeInfo, jd) - if err != nil { - return nil, nil, fmt.Errorf("failed to create registered DON: %w", err) + if jd == nil || jd.don == nil { + return nil, nil, fmt.Errorf("offchain client does not have a DON") } - nodeIDs := don.NodeIds() - err = don.CreateSupportedChains(ctx, config.Chains, jd) + err = jd.don.CreateSupportedChains(ctx, config.Chains, *jd) if err != nil { return nil, nil, err } + nodeIDs := jd.don.NodeIds() return &deployment.Environment{ Name: DevEnv, @@ -52,5 +50,5 @@ func NewEnvironment(ctx context.Context, lggr logger.Logger, config EnvironmentC NodeIDs: nodeIDs, Chains: chains, Logger: lggr, - }, don, nil + }, jd.don, nil } diff --git a/integration-tests/deployment/devenv/jd.go b/integration-tests/deployment/devenv/jd.go index 671e6e4cea3..7a8183f04aa 100644 --- a/integration-tests/deployment/devenv/jd.go +++ b/integration-tests/deployment/devenv/jd.go @@ -15,9 +15,10 @@ import ( ) type JDConfig struct { - GRPC string - WSRPC string - creds credentials.TransportCredentials + GRPC string + WSRPC string + creds credentials.TransportCredentials + nodeInfo []NodeInfo } func NewJDConnection(cfg JDConfig) (*grpc.ClientConn, error) { @@ -43,19 +44,25 @@ type JobDistributor struct { nodev1.NodeServiceClient jobv1.JobServiceClient csav1.CSAServiceClient + don *DON } -func NewJDClient(cfg JDConfig) (deployment.OffchainClient, error) { +func NewJDClient(ctx context.Context, cfg JDConfig) (deployment.OffchainClient, error) { conn, err := NewJDConnection(cfg) if err != nil { return nil, fmt.Errorf("failed to connect Job Distributor service. Err: %w", err) } - return JobDistributor{ + jd := &JobDistributor{ WSRPC: cfg.WSRPC, NodeServiceClient: nodev1.NewNodeServiceClient(conn), JobServiceClient: jobv1.NewJobServiceClient(conn), CSAServiceClient: csav1.NewCSAServiceClient(conn), - }, err + } + jd.don, err = NewRegisteredDON(ctx, cfg.nodeInfo, *jd) + if err != nil { + return nil, fmt.Errorf("failed to create registered DON: %w", err) + } + return jd, err } func (jd JobDistributor) GetCSAPublicKey(ctx context.Context) (string, error) { @@ -69,3 +76,28 @@ func (jd JobDistributor) GetCSAPublicKey(ctx context.Context) (string, error) { csakey := keypairs.Keypairs[0].PublicKey return csakey, nil } + +func (jd JobDistributor) ReplayLogs(selectorToBlock map[uint64]uint64) error { + return jd.don.ReplayAllLogs(selectorToBlock) +} + +// ProposeJob proposes jobs through the jobService and accepts the proposed job on selected node based on ProposeJobRequest.NodeId +func (jd JobDistributor) ProposeJob(ctx context.Context, in *jobv1.ProposeJobRequest, opts ...grpc.CallOption) (*jobv1.ProposeJobResponse, error) { + res, err := jd.JobServiceClient.ProposeJob(ctx, in, opts...) + if err != nil { + return nil, fmt.Errorf("failed to propose job. err: %w", err) + } + if res.Proposal == nil { + return nil, fmt.Errorf("failed to propose job. err: proposal is nil") + } + for _, node := range jd.don.Nodes { + if node.NodeId != in.NodeId { + continue + } + // TODO : is there a way to accept the job with proposal id? + if err := node.AcceptJob(ctx, res.Proposal.Spec); err != nil { + return nil, fmt.Errorf("failed to accept job. err: %w", err) + } + } + return res, nil +} diff --git a/integration-tests/deployment/helpers.go b/integration-tests/deployment/helpers.go index 5e81eadd39d..d3857c8c4fd 100644 --- a/integration-tests/deployment/helpers.go +++ b/integration-tests/deployment/helpers.go @@ -68,6 +68,9 @@ func ParseErrorFromABI(errorString string, contractABI string) (string, error) { if err != nil { return "", errors.Wrap(err, "error decoding error string") } + if len(data) < 4 { + return "", errors.Errorf("error data too short %s", data) + } for errorName, abiError := range parsedAbi.Errors { if bytes.Equal(data[:4], abiError.ID.Bytes()[:4]) { // Found a matching error diff --git a/integration-tests/deployment/memory/environment.go b/integration-tests/deployment/memory/environment.go index 409e8d3a816..2b68d5666fa 100644 --- a/integration-tests/deployment/memory/environment.go +++ b/integration-tests/deployment/memory/environment.go @@ -112,23 +112,6 @@ func NewMemoryEnvironmentFromChainsNodes(t *testing.T, } } -//func NewMemoryEnvironmentExistingChains(t *testing.T, lggr logger.Logger, -// chains map[uint64]deployment.Chain, config MemoryEnvironmentConfig) deployment.Environment { -// nodes := NewNodes(t, chains, config.Nodes, config.Bootstraps, config.CapabilityRegistryConfig) -// var nodeIDs []string -// for id := range nodes { -// nodeIDs = append(nodeIDs, id) -// } -// return deployment.Environment{ -// Name: Memory, -// Offchain: NewMemoryJobClient(nodes), -// // Note these have the p2p_ prefix. -// NodeIDs: nodeIDs, -// Chains: chains, -// Logger: lggr, -// } -//} - // To be used by tests and any kind of deployment logic. func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Level, config MemoryEnvironmentConfig) deployment.Environment { chains := NewMemoryChains(t, config.Chains) diff --git a/integration-tests/deployment/memory/job_client.go b/integration-tests/deployment/memory/job_client.go index 25fec711d81..16dbfc2b828 100644 --- a/integration-tests/deployment/memory/job_client.go +++ b/integration-tests/deployment/memory/job_client.go @@ -156,6 +156,15 @@ func (j JobClient) DeleteJob(ctx context.Context, in *jobv1.DeleteJobRequest, op panic("implement me") } +func (j JobClient) ReplayLogs(selectorToBlock map[uint64]uint64) error { + for _, node := range j.Nodes { + if err := node.ReplayLogs(selectorToBlock); err != nil { + return err + } + } + return nil +} + func NewMemoryJobClient(nodesByPeerID map[string]Node) *JobClient { return &JobClient{nodesByPeerID} } diff --git a/integration-tests/deployment/multiclient.go b/integration-tests/deployment/multiclient.go index 29056492074..fb30799ed0b 100644 --- a/integration-tests/deployment/multiclient.go +++ b/integration-tests/deployment/multiclient.go @@ -8,12 +8,12 @@ import ( "runtime" "time" - "github.com/avast/retry-go/v4" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/pkg/errors" + "github.com/sethvargo/go-retry" "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -23,7 +23,7 @@ const ( ) type RetryConfig struct { - Attempts uint + Attempts uint64 Delay time.Duration } @@ -49,7 +49,7 @@ type MultiClient struct { RetryConfig RetryConfig } -func WithRetryConfig(attempts uint, delay time.Duration) func(client *MultiClient) { +func WithRetryConfig(attempts uint64, delay time.Duration) func(client *MultiClient) { return func(client *MultiClient) { client.RetryConfig = RetryConfig{ Attempts: attempts, @@ -92,10 +92,80 @@ func NewMultiClient(lggr logger.Logger, rpcs []RPC, opts ...func(client *MultiCl return mc, nil } +func (mc *MultiClient) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + var header *types.Header + err := mc.retryWithBackups(ctx, func(client *ethclient.Client) error { + var err error + header, err = client.HeaderByNumber(ctx, number) + return err + }) + return header, err +} + +func (mc *MultiClient) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { + var result []byte + err := mc.retryWithBackups(ctx, func(client *ethclient.Client) error { + var err error + result, err = client.CallContract(ctx, call, blockNumber) + return err + }) + return result, err +} + +func (mc *MultiClient) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { + var code []byte + err := mc.retryWithBackups(ctx, func(client *ethclient.Client) error { + var err error + code, err = client.PendingCodeAt(ctx, account) + return err + }) + return code, err +} + +func (mc *MultiClient) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { + var count uint64 + err := mc.retryWithBackups(ctx, func(client *ethclient.Client) error { + var err error + count, err = client.PendingNonceAt(ctx, account) + return err + }) + return count, err +} + +func (mc *MultiClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + var price *big.Int + err := mc.retryWithBackups(ctx, func(client *ethclient.Client) error { + var err error + price, err = client.SuggestGasPrice(ctx) + return err + }) + return price, err +} + +func (mc *MultiClient) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) { + var gas uint64 + err := mc.retryWithBackups(ctx, func(client *ethclient.Client) error { + var err error + gas, err = client.EstimateGas(ctx, call) + return err + }) + return gas, err +} + +func (mc *MultiClient) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { + var tipCap *big.Int + err := mc.retryWithBackups(ctx, func(client *ethclient.Client) error { + var err error + tipCap, err = client.SuggestGasTipCap(ctx) + return err + }) + return tipCap, err +} + func (mc *MultiClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { var receipt *types.Receipt // TransactionReceipt might return ethereum.NotFound error if the transaction is not yet mined - err := mc.retryWithBackups(func(client *ethclient.Client) error { + err := mc.retryWithBackups(ctx, func(client *ethclient.Client) error { var err error receipt, err = client.TransactionReceipt(ctx, txHash) return err @@ -104,14 +174,14 @@ func (mc *MultiClient) TransactionReceipt(ctx context.Context, txHash common.Has } func (mc *MultiClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { - return mc.retryWithBackups(func(client *ethclient.Client) error { + return mc.retryWithBackups(ctx, func(client *ethclient.Client) error { return client.SendTransaction(ctx, tx) }) } func (mc *MultiClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { var code []byte - err := mc.retryWithBackups(func(client *ethclient.Client) error { + err := mc.retryWithBackups(ctx, func(client *ethclient.Client) error { var err error code, err = client.CodeAt(ctx, account, blockNumber) return err @@ -121,7 +191,7 @@ func (mc *MultiClient) CodeAt(ctx context.Context, account common.Address, block func (mc *MultiClient) NonceAt(ctx context.Context, account common.Address) (uint64, error) { var count uint64 - err := mc.retryWithBackups(func(client *ethclient.Client) error { + err := mc.retryWithBackups(ctx, func(client *ethclient.Client) error { var err error count, err = client.NonceAt(ctx, account, nil) return err @@ -129,30 +199,35 @@ func (mc *MultiClient) NonceAt(ctx context.Context, account common.Address) (uin return count, err } -func (mc *MultiClient) retryWithBackups(op func(*ethclient.Client) error, acceptedErrors ...error) error { +func (mc *MultiClient) retryWithBackups(ctx context.Context, op func(*ethclient.Client) error, acceptedErrors ...error) error { var err2 error funcName := runtime.FuncForPC(reflect.ValueOf(op).Pointer()).Name() for i, client := range append([]*ethclient.Client{mc.Client}, mc.Backups...) { - err2 = retry.Do(func() error { - err := op(client) - if err != nil { - // Check if the error is one of the accepted errors - // If it is, log it and return nil - for _, acceptedError := range acceptedErrors { - if errors.Is(err, acceptedError) { - mc.logger.Debugf("acceptable error %+v with client %d for op %s", err, i+1, funcName) - return nil + err2 = retry.Do(ctx, retry.WithMaxRetries(mc.RetryConfig.Attempts, retry.NewConstant(mc.RetryConfig.Delay)), + func(ctx context.Context) error { + err := op(client) + if err != nil { + // Check if the error is one of the accepted errors + // If it is, log it and return nil + for _, acceptedError := range acceptedErrors { + if errors.Is(err, acceptedError) { + return err + } } + mc.logger.Warnf("error %+v with client %d for op %s", err, i+1, funcName) + return retry.RetryableError(err) } - mc.logger.Warnf("error %+v with client %d for op %s", err, i+1, funcName) - return err - } - return nil - }, retry.Attempts(mc.RetryConfig.Attempts), retry.Delay(mc.RetryConfig.Delay)) + return nil + }) if err2 == nil { return nil } - fmt.Printf("Client %d failed, trying next client\n", i+1) + for _, acceptedError := range acceptedErrors { + if errors.Is(err2, acceptedError) { + return err2 + } + } + mc.logger.Infof("Client %d failed, trying next client\n", i+1) } return errors.Wrapf(err2, "All backup clients %v failed", mc.Backups) } diff --git a/integration-tests/smoke/ccip_test.go b/integration-tests/smoke/ccip_test.go index c56417b1c5d..393afae5e05 100644 --- a/integration-tests/smoke/ccip_test.go +++ b/integration-tests/smoke/ccip_test.go @@ -1,9 +1,11 @@ package smoke import ( - "strconv" + "fmt" "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" @@ -11,78 +13,83 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - ccipdeployment "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + ccdeploy "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/changeset" "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/view" jobv1 "github.com/smartcontractkit/chainlink/integration-tests/deployment/jd/job/v1" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/logger" ) +func TestRevert(t *testing.T) { + ec, err := ethclient.Dial("wss...") + require.NoError(t, err) + tx, _, err := ec.TransactionByHash(testcontext.Get(t), common.HexToHash("0x6aae71ad356d383a41d20aad69de4e1cde536c33b0a41488e529df731bf086ab")) + require.NoError(t, err) + rec, err := ec.TransactionReceipt(testcontext.Get(t), tx.Hash()) + require.NoError(t, err) + fromTx, err := deployment.GetErrorReasonFromTx(ec, common.HexToAddress("0xBE7294B7910606845500Ba524FfcAC8917A00F34"), *tx, rec) + require.NoError(t, err) + errStr, err := deployment.ParseErrorFromABI(fromTx, capabilities_registry.CapabilitiesRegistryABI) + require.NoError(t, err) + fmt.Println(errStr) +} + func Test0002_InitialDeployOnLocal(t *testing.T) { lggr := logger.TestLogger(t) ctx := testcontext.Get(t) - tenv := ccipdeployment.NewDeployedLocalDevEnvironment(t, lggr) + tenv := ccdeploy.NewLocalDevEnvironment(t, lggr) + e := tenv.Env - don := tenv.DON - state, err := ccipdeployment.LoadOnchainState(tenv.Env, tenv.Ab) + state, err := ccdeploy.LoadOnchainState(tenv.Env, tenv.Ab) require.NoError(t, err) feeds := state.Chains[tenv.FeedChainSel].USDFeeds - tokenConfig := ccipdeployment.NewTokenConfig() - tokenConfig.UpsertTokenInfo(ccipdeployment.LinkSymbol, + tokenConfig := ccdeploy.NewTokenConfig() + tokenConfig.UpsertTokenInfo(ccdeploy.LinkSymbol, pluginconfig.TokenInfo{ - AggregatorAddress: feeds[ccipdeployment.LinkSymbol].Address().String(), - Decimals: ccipdeployment.LinkDecimals, + AggregatorAddress: feeds[ccdeploy.LinkSymbol].Address().String(), + Decimals: ccdeploy.LinkDecimals, DeviationPPB: cciptypes.NewBigIntFromInt64(1e9), }, ) // Apply migration - output, err := changeset.Apply0002(tenv.Env, ccipdeployment.DeployCCIPContractConfig{ + output, err := changeset.Apply0002(tenv.Env, ccdeploy.DeployCCIPContractConfig{ HomeChainSel: tenv.HomeChainSel, FeedChainSel: tenv.FeedChainSel, - TokenConfig: tokenConfig, ChainsToDeploy: tenv.Env.AllChainSelectors(), - // Capreg/config already exist. + TokenConfig: tokenConfig, + // Capreg/config and feeds already exist. CCIPOnChainState: state, }) require.NoError(t, err) // Get new state after migration. - state, err = ccipdeployment.LoadOnchainState(e, output.AddressBook) + state, err = ccdeploy.LoadOnchainState(e, output.AddressBook) require.NoError(t, err) + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + // Apply the jobs. - nodeIdToJobIds := make(map[string][]string) for nodeID, jobs := range output.JobSpecs { - nodeIdToJobIds[nodeID] = make([]string, 0, len(jobs)) for _, job := range jobs { - res, err := e.Offchain.ProposeJob(ctx, + // Note these auto-accept + _, err := e.Offchain.ProposeJob(ctx, &jobv1.ProposeJobRequest{ NodeId: nodeID, Spec: job, }) require.NoError(t, err) - require.NotNil(t, res.Proposal) - nodeIdToJobIds[nodeID] = append(nodeIdToJobIds[nodeID], res.Proposal.JobId) - } - } - - // Accept all the jobs for this node. - for _, n := range don.Nodes { - jobsToAccept, exists := nodeIdToJobIds[n.NodeId] - require.True(t, exists, "node %s has no jobs to accept", n.NodeId) - for i, jobID := range jobsToAccept { - require.NoError(t, n.AcceptJob(ctx, strconv.Itoa(i+1)), "node -%s failed to accept job %s", n.Name, jobID) } } - t.Log("Jobs accepted") // Add all lanes - require.NoError(t, ccipdeployment.AddLanesForAll(e, state)) + require.NoError(t, ccdeploy.AddLanesForAll(e, state)) v, err := state.View(e.AllChainSelectors()) require.NoError(t, err) require.NoError(t, view.SaveView(v)) - // Need to keep track of the block number for each chain so that event subscription can be done from that block. startBlocks := make(map[uint64]*uint64) // Send a message from each chain to every other chain. @@ -96,13 +103,13 @@ func Test0002_InitialDeployOnLocal(t *testing.T) { require.NoError(t, err) block := latesthdr.Number.Uint64() startBlocks[dest] = &block - seqNum := ccipdeployment.SendRequest(t, e, state, src, dest, false) + seqNum := ccdeploy.SendRequest(t, e, state, src, dest, false) expectedSeqNum[dest] = seqNum } } // Wait for all commit reports to land. - ccipdeployment.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) // After commit is reported on all chains, token prices should be updated in FeeQuoter. for dest := range e.Chains { @@ -110,8 +117,11 @@ func Test0002_InitialDeployOnLocal(t *testing.T) { feeQuoter := state.Chains[dest].FeeQuoter timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) require.NoError(t, err) - require.Equal(t, ccipdeployment.MockLinkPrice, timestampedPrice.Value) + require.Equal(t, ccdeploy.MockLinkPrice, timestampedPrice.Value) } + // Wait for all exec reports to land - ccipdeployment.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) + ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) + + // TODO: Apply the proposal. } diff --git a/integration-tests/web/sdk/client/client.go b/integration-tests/web/sdk/client/client.go index 783a8a88565..e633bf04c15 100644 --- a/integration-tests/web/sdk/client/client.go +++ b/integration-tests/web/sdk/client/client.go @@ -21,12 +21,13 @@ type Client interface { FetchOCR2KeyBundleID(ctx context.Context, chainType string) (string, error) GetJob(ctx context.Context, id string) (*generated.GetJobResponse, error) ListJobs(ctx context.Context, offset, limit int) (*generated.ListJobsResponse, error) - GetJobDistributor(ctx context.Context, id string) (*generated.GetFeedsManagerResponse, error) + GetJobDistributor(ctx context.Context, id string) (generated.FeedsManagerParts, error) ListJobDistributors(ctx context.Context) (*generated.ListFeedsManagersResponse, error) CreateJobDistributor(ctx context.Context, cmd JobDistributorInput) (string, error) UpdateJobDistributor(ctx context.Context, id string, cmd JobDistributorInput) error - CreateJobDistributorChainConfig(ctx context.Context, in JobDistributorChainConfigInput) error - GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalResponse, error) + CreateJobDistributorChainConfig(ctx context.Context, in JobDistributorChainConfigInput) (string, error) + DeleteJobDistributorChainConfig(ctx context.Context, id string) error + GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalJobProposal, error) ApproveJobProposalSpec(ctx context.Context, id string, force bool) (*JobProposalApprovalSuccessSpec, error) CancelJobProposalSpec(ctx context.Context, id string) (*generated.CancelJobProposalSpecResponse, error) RejectJobProposalSpec(ctx context.Context, id string) (*generated.RejectJobProposalSpecResponse, error) @@ -142,8 +143,18 @@ func (c *client) ListBridges(ctx context.Context, offset, limit int) (*generated return generated.ListBridges(ctx, c.gqlClient, offset, limit) } -func (c *client) GetJobDistributor(ctx context.Context, id string) (*generated.GetFeedsManagerResponse, error) { - return generated.GetFeedsManager(ctx, c.gqlClient, id) +func (c *client) GetJobDistributor(ctx context.Context, id string) (generated.FeedsManagerParts, error) { + res, err := generated.GetFeedsManager(ctx, c.gqlClient, id) + if err != nil { + return generated.FeedsManagerParts{}, err + } + if res == nil { + return generated.FeedsManagerParts{}, fmt.Errorf("no feeds manager found") + } + if success, ok := res.GetFeedsManager().(*generated.GetFeedsManagerFeedsManager); ok { + return success.FeedsManagerParts, nil + } + return generated.FeedsManagerParts{}, fmt.Errorf("failed to get feeds manager") } func (c *client) ListJobDistributors(ctx context.Context) (*generated.ListFeedsManagersResponse, error) { @@ -178,18 +189,51 @@ func (c *client) UpdateJobDistributor(ctx context.Context, id string, in JobDist return err } -func (c *client) CreateJobDistributorChainConfig(ctx context.Context, in JobDistributorChainConfigInput) error { +func (c *client) CreateJobDistributorChainConfig(ctx context.Context, in JobDistributorChainConfigInput) (string, error) { var cmd generated.CreateFeedsManagerChainConfigInput err := DecodeInput(in, &cmd) + if err != nil { + return "", err + } + res, err := generated.CreateFeedsManagerChainConfig(ctx, c.gqlClient, cmd) + if err != nil { + return "", err + } + if res == nil { + return "", fmt.Errorf("failed to create feeds manager chain config") + } + if success, ok := res.GetCreateFeedsManagerChainConfig().(*generated.CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess); ok { + return success.ChainConfig.Id, nil + } + return "", fmt.Errorf("failed to create feeds manager chain config") +} + +func (c *client) DeleteJobDistributorChainConfig(ctx context.Context, id string) error { + res, err := generated.DeleteFeedsManagerChainConfig(ctx, c.gqlClient, id) if err != nil { return err } - _, err = generated.CreateFeedsManagerChainConfig(ctx, c.gqlClient, cmd) - return err + if res == nil { + return fmt.Errorf("failed to delete feeds manager chain config") + } + if _, ok := res.GetDeleteFeedsManagerChainConfig().(*generated.DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess); ok { + return nil + } + return fmt.Errorf("failed to delete feeds manager chain config") } -func (c *client) GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalResponse, error) { - return generated.GetJobProposal(ctx, c.gqlClient, id) +func (c *client) GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalJobProposal, error) { + proposal, err := generated.GetJobProposal(ctx, c.gqlClient, id) + if err != nil { + return nil, err + } + if proposal == nil { + return nil, fmt.Errorf("no job proposal found") + } + if success, ok := proposal.GetJobProposal().(*generated.GetJobProposalJobProposal); ok { + return success, nil + } + return nil, fmt.Errorf("failed to get job proposal") } func (c *client) ApproveJobProposalSpec(ctx context.Context, id string, force bool) (*JobProposalApprovalSuccessSpec, error) { diff --git a/integration-tests/web/sdk/internal/generated/generated.go b/integration-tests/web/sdk/internal/generated/generated.go index 8efde4c453f..68ab3e48e4f 100644 --- a/integration-tests/web/sdk/internal/generated/generated.go +++ b/integration-tests/web/sdk/internal/generated/generated.go @@ -1194,6 +1194,11 @@ func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManag return v.FeedsManagerParts.CreatedAt } +// GetJobProposals returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) UnmarshalJSON(b []byte) error { if string(b) == "null" { @@ -1231,6 +1236,8 @@ type __premarshalCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFe IsConnectionActive bool `json:"isConnectionActive"` CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) MarshalJSON() ([]byte, error) { @@ -1250,6 +1257,7 @@ func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManag retval.PublicKey = v.FeedsManagerParts.PublicKey retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals return &retval, nil } @@ -1425,6 +1433,200 @@ func (v *CreateFeedsManagerResponse) __premarshalJSON() (*__premarshalCreateFeed return &retval, nil } +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload includes the requested fields of the GraphQL interface DeleteFeedsManagerChainConfigPayload. +// +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload is implemented by the following types: +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload interface { + implementsGraphQLInterfaceDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) implementsGraphQLInterfaceDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload() { +} +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) implementsGraphQLInterfaceDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload() { +} + +func __unmarshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload(b []byte, v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "DeleteFeedsManagerChainConfigSuccess": + *v = new(DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing DeleteFeedsManagerChainConfigPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload: "%v"`, tn.TypeName) + } +} + +func __marshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload(v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess: + typename = "DeleteFeedsManagerChainConfigSuccess" + + result := struct { + TypeName string `json:"__typename"` + *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess + }{typename, v} + return json.Marshal(result) + case *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload: "%T"`, v) + } +} + +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess includes the requested fields of the GraphQL type DeleteFeedsManagerChainConfigSuccess. +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess struct { + Typename string `json:"__typename"` + ChainConfig DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig `json:"chainConfig"` +} + +// GetTypename returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess.Typename, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) GetTypename() string { + return v.Typename +} + +// GetChainConfig returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess.ChainConfig, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) GetChainConfig() DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig { + return v.ChainConfig +} + +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig includes the requested fields of the GraphQL type FeedsManagerChainConfig. +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig struct { + Id string `json:"id"` +} + +// GetId returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.Id, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetId() string { + return v.Id +} + +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) GetTypename() string { + return v.Typename +} + +// GetMessage returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) GetMessage() string { + return v.Message +} + +// GetCode returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) GetCode() ErrorCode { + return v.Code +} + +// DeleteFeedsManagerChainConfigResponse is returned by DeleteFeedsManagerChainConfig on success. +type DeleteFeedsManagerChainConfigResponse struct { + DeleteFeedsManagerChainConfig DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload `json:"-"` +} + +// GetDeleteFeedsManagerChainConfig returns DeleteFeedsManagerChainConfigResponse.DeleteFeedsManagerChainConfig, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigResponse) GetDeleteFeedsManagerChainConfig() DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload { + return v.DeleteFeedsManagerChainConfig +} + +func (v *DeleteFeedsManagerChainConfigResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *DeleteFeedsManagerChainConfigResponse + DeleteFeedsManagerChainConfig json.RawMessage `json:"deleteFeedsManagerChainConfig"` + graphql.NoUnmarshalJSON + } + firstPass.DeleteFeedsManagerChainConfigResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.DeleteFeedsManagerChainConfig + src := firstPass.DeleteFeedsManagerChainConfig + if len(src) != 0 && string(src) != "null" { + err = __unmarshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal DeleteFeedsManagerChainConfigResponse.DeleteFeedsManagerChainConfig: %w", err) + } + } + } + return nil +} + +type __premarshalDeleteFeedsManagerChainConfigResponse struct { + DeleteFeedsManagerChainConfig json.RawMessage `json:"deleteFeedsManagerChainConfig"` +} + +func (v *DeleteFeedsManagerChainConfigResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *DeleteFeedsManagerChainConfigResponse) __premarshalJSON() (*__premarshalDeleteFeedsManagerChainConfigResponse, error) { + var retval __premarshalDeleteFeedsManagerChainConfigResponse + + { + + dst := &retval.DeleteFeedsManagerChainConfig + src := v.DeleteFeedsManagerChainConfig + var err error + *dst, err = __marshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal DeleteFeedsManagerChainConfigResponse.DeleteFeedsManagerChainConfig: %w", err) + } + } + return &retval, nil +} + type ErrorCode string const ( @@ -1435,12 +1637,13 @@ const ( // FeedsManagerParts includes the GraphQL fields of FeedsManager requested by the fragment FeedsManagerParts. type FeedsManagerParts struct { - Id string `json:"id"` - Name string `json:"name"` - Uri string `json:"uri"` - PublicKey string `json:"publicKey"` - IsConnectionActive bool `json:"isConnectionActive"` - CreatedAt string `json:"createdAt"` + Id string `json:"id"` + Name string `json:"name"` + Uri string `json:"uri"` + PublicKey string `json:"publicKey"` + IsConnectionActive bool `json:"isConnectionActive"` + CreatedAt string `json:"createdAt"` + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } // GetId returns FeedsManagerParts.Id, and is useful for accessing the field via an interface. @@ -1461,6 +1664,137 @@ func (v *FeedsManagerParts) GetIsConnectionActive() bool { return v.IsConnection // GetCreatedAt returns FeedsManagerParts.CreatedAt, and is useful for accessing the field via an interface. func (v *FeedsManagerParts) GetCreatedAt() string { return v.CreatedAt } +// GetJobProposals returns FeedsManagerParts.JobProposals, and is useful for accessing the field via an interface. +func (v *FeedsManagerParts) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.JobProposals +} + +// FeedsManagerPartsJobProposalsJobProposal includes the requested fields of the GraphQL type JobProposal. +type FeedsManagerPartsJobProposalsJobProposal struct { + Id string `json:"id"` + Status JobProposalStatus `json:"status"` + RemoteUUID string `json:"remoteUUID"` + ExternalJobID string `json:"externalJobID"` + JobID string `json:"jobID"` + Specs []FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec `json:"specs"` + LatestSpec FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec `json:"latestSpec"` +} + +// GetId returns FeedsManagerPartsJobProposalsJobProposal.Id, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetId() string { return v.Id } + +// GetStatus returns FeedsManagerPartsJobProposalsJobProposal.Status, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetStatus() JobProposalStatus { return v.Status } + +// GetRemoteUUID returns FeedsManagerPartsJobProposalsJobProposal.RemoteUUID, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetRemoteUUID() string { return v.RemoteUUID } + +// GetExternalJobID returns FeedsManagerPartsJobProposalsJobProposal.ExternalJobID, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetExternalJobID() string { return v.ExternalJobID } + +// GetJobID returns FeedsManagerPartsJobProposalsJobProposal.JobID, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetJobID() string { return v.JobID } + +// GetSpecs returns FeedsManagerPartsJobProposalsJobProposal.Specs, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetSpecs() []FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec { + return v.Specs +} + +// GetLatestSpec returns FeedsManagerPartsJobProposalsJobProposal.LatestSpec, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetLatestSpec() FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec { + return v.LatestSpec +} + +// FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetId() string { + return v.Id +} + +// GetDefinition returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetVersion() int { + return v.Version +} + +// GetStatus returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetStatus() SpecStatus { + return v.Status +} + +// GetStatusUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + +// FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetId() string { return v.Id } + +// GetDefinition returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetVersion() int { + return v.Version +} + +// GetStatus returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetStatus() SpecStatus { + return v.Status +} + +// GetStatusUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + // FetchAccountsEthKeysEthKeysPayload includes the requested fields of the GraphQL type EthKeysPayload. type FetchAccountsEthKeysEthKeysPayload struct { Results []FetchAccountsEthKeysEthKeysPayloadResultsEthKey `json:"results"` @@ -1929,6 +2263,11 @@ func (v *GetFeedsManagerFeedsManager) GetIsConnectionActive() bool { // GetCreatedAt returns GetFeedsManagerFeedsManager.CreatedAt, and is useful for accessing the field via an interface. func (v *GetFeedsManagerFeedsManager) GetCreatedAt() string { return v.FeedsManagerParts.CreatedAt } +// GetJobProposals returns GetFeedsManagerFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + func (v *GetFeedsManagerFeedsManager) UnmarshalJSON(b []byte) error { if string(b) == "null" { @@ -1968,6 +2307,8 @@ type __premarshalGetFeedsManagerFeedsManager struct { IsConnectionActive bool `json:"isConnectionActive"` CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } func (v *GetFeedsManagerFeedsManager) MarshalJSON() ([]byte, error) { @@ -1988,6 +2329,7 @@ func (v *GetFeedsManagerFeedsManager) __premarshalJSON() (*__premarshalGetFeedsM retval.PublicKey = v.FeedsManagerParts.PublicKey retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals return &retval, nil } @@ -2465,6 +2807,11 @@ func (v *GetJobProposalJobProposalFeedsManager) GetCreatedAt() string { return v.FeedsManagerParts.CreatedAt } +// GetJobProposals returns GetJobProposalJobProposalFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + func (v *GetJobProposalJobProposalFeedsManager) UnmarshalJSON(b []byte) error { if string(b) == "null" { @@ -2502,6 +2849,8 @@ type __premarshalGetJobProposalJobProposalFeedsManager struct { IsConnectionActive bool `json:"isConnectionActive"` CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } func (v *GetJobProposalJobProposalFeedsManager) MarshalJSON() ([]byte, error) { @@ -2521,6 +2870,7 @@ func (v *GetJobProposalJobProposalFeedsManager) __premarshalJSON() (*__premarsha retval.PublicKey = v.FeedsManagerParts.PublicKey retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals return &retval, nil } @@ -3650,6 +4000,11 @@ func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) return v.FeedsManagerParts.CreatedAt } +// GetJobProposals returns ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) UnmarshalJSON(b []byte) error { if string(b) == "null" { @@ -3687,6 +4042,8 @@ type __premarshalListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsM IsConnectionActive bool `json:"isConnectionActive"` CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) MarshalJSON() ([]byte, error) { @@ -3706,6 +4063,7 @@ func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) retval.PublicKey = v.FeedsManagerParts.PublicKey retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals return &retval, nil } @@ -4469,6 +4827,11 @@ func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManag return v.FeedsManagerParts.CreatedAt } +// GetJobProposals returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) UnmarshalJSON(b []byte) error { if string(b) == "null" { @@ -4506,6 +4869,8 @@ type __premarshalUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFe IsConnectionActive bool `json:"isConnectionActive"` CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) MarshalJSON() ([]byte, error) { @@ -4525,6 +4890,7 @@ func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManag retval.PublicKey = v.FeedsManagerParts.PublicKey retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals return &retval, nil } @@ -4803,6 +5169,14 @@ type __CreateFeedsManagerInput struct { // GetInput returns __CreateFeedsManagerInput.Input, and is useful for accessing the field via an interface. func (v *__CreateFeedsManagerInput) GetInput() CreateFeedsManagerInput { return v.Input } +// __DeleteFeedsManagerChainConfigInput is used internally by genqlient +type __DeleteFeedsManagerChainConfigInput struct { + Id string `json:"id"` +} + +// GetId returns __DeleteFeedsManagerChainConfigInput.Id, and is useful for accessing the field via an interface. +func (v *__DeleteFeedsManagerChainConfigInput) GetId() string { return v.Id } + // __GetBridgeInput is used internally by genqlient type __GetBridgeInput struct { Id string `json:"id"` @@ -5033,6 +5407,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } ` @@ -5142,6 +5541,50 @@ func CreateFeedsManagerChainConfig( return &data_, err_ } +// The query or mutation executed by DeleteFeedsManagerChainConfig. +const DeleteFeedsManagerChainConfig_Operation = ` +mutation DeleteFeedsManagerChainConfig ($id: ID!) { + deleteFeedsManagerChainConfig(id: $id) { + __typename + ... on DeleteFeedsManagerChainConfigSuccess { + chainConfig { + id + } + } + ... on NotFoundError { + message + code + } + } +} +` + +func DeleteFeedsManagerChainConfig( + ctx_ context.Context, + client_ graphql.Client, + id string, +) (*DeleteFeedsManagerChainConfigResponse, error) { + req_ := &graphql.Request{ + OpName: "DeleteFeedsManagerChainConfig", + Query: DeleteFeedsManagerChainConfig_Operation, + Variables: &__DeleteFeedsManagerChainConfigInput{ + Id: id, + }, + } + var err_ error + + var data_ DeleteFeedsManagerChainConfigResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + // The query or mutation executed by FetchAccounts. const FetchAccounts_Operation = ` query FetchAccounts { @@ -5357,6 +5800,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } ` @@ -5514,6 +5982,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } ` @@ -5610,6 +6103,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } ` @@ -5796,6 +6314,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } ` diff --git a/integration-tests/web/sdk/internal/genqlient.graphql b/integration-tests/web/sdk/internal/genqlient.graphql index cd1912b88cf..06baf4f7913 100644 --- a/integration-tests/web/sdk/internal/genqlient.graphql +++ b/integration-tests/web/sdk/internal/genqlient.graphql @@ -212,6 +212,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } query GetFeedsManager($id: ID!) { @@ -328,6 +353,19 @@ mutation CreateFeedsManagerChainConfig($input: CreateFeedsManagerChainConfigInpu } } +mutation DeleteFeedsManagerChainConfig($id: ID!) { + deleteFeedsManagerChainConfig(id: $id) { + ... on DeleteFeedsManagerChainConfigSuccess { + chainConfig { + id + } + } + ... on NotFoundError { + message + code + } + } +} ##################### # Job Proposals @@ -418,4 +456,4 @@ mutation UpdateJobProposalSpecDefinition( code } } -} +} \ No newline at end of file