Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions plugins/plugins.public.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ defaults:
plugins:
aptos:
- moduleURI: "github.com/smartcontractkit/chainlink-aptos"
gitRef: "v0.0.0-20260828090428-9828cc37ebc2"
gitRef: "v0.0.0-20261015141323-398fb19195f8"
installPath: "./cmd/chainlink-aptos"

sui:
Expand Down Expand Up @@ -94,7 +94,7 @@ plugins:

capability-aptos:
- moduleURI: "github.com/smartcontractkit/capabilities/chain_capabilities/aptos"
gitRef: "8c63e69b4e241875e7e111d6e85d8d0596f22981"
gitRef: "9e93a8af323420aa671705eb619c7ea533041036"
installPath: "."

capability-stellar:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ type Config struct {
ChainSelector uint64 `yaml:"chainSelector"`
WorkflowName string `yaml:"workflowName"`
ExpectedCoinName string `yaml:"expectedCoinName"` // expected exact value in the View reply data (e.g. "Aptos Coin" for 0x1::coin::name())
// ExpectUserError switches the workflow to call View on a module that doesn't exist and assert
// the capability classifies the resulting Aptos node 400 as a user error.
ExpectUserError bool `yaml:"expectUserError"`
}
34 changes: 34 additions & 0 deletions system-tests/tests/smoke/cre/aptos/aptosread/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ func onAptosReadTrigger(cfg config.Config, runtime sdk.Runtime, payload *cron.Pa
}()

client := aptos.Client{ChainSelector: cfg.ChainSelector}
if cfg.ExpectUserError {
return runViewUserErrorCheck(cfg, runtime, client)
}

reply, err := client.View(runtime, &aptos.ViewRequest{
Payload: &aptos.ViewPayload{
Module: &aptos.ModuleID{
Expand Down Expand Up @@ -101,6 +105,36 @@ func onAptosReadTrigger(cfg config.Config, runtime sdk.Runtime, payload *cron.Pa
return nil, nil
}

// userErrorPrefix is how the host serialises a public user-origin capability error for the guest
// (visibility:origin:code:message).
const userErrorPrefix = "Public:User:"

// runViewUserErrorCheck calls View on a module that doesn't exist under 0x1. The Aptos node rejects
// it with HTTP 400 (Linker Error), which the capability must surface as a user error.
func runViewUserErrorCheck(cfg config.Config, runtime sdk.Runtime, client aptos.Client) (any, error) {
_, err := client.View(runtime, &aptos.ViewRequest{
Payload: &aptos.ViewPayload{
Module: &aptos.ModuleID{
Address: []byte{0x1},
Name: "cre_e2e_missing_module",
},
Function: "missing",
},
}).Await()
if err == nil {
runtime.Logger().Info("Aptos view user error test failed: expected error, got reply", "workflow", cfg.WorkflowName)
return nil, errors.New("expected View on missing module to fail")
}
if !strings.HasPrefix(err.Error(), userErrorPrefix) {
msg := fmt.Sprintf("Aptos view user error test failed: unexpected classification: %v", err)
runtime.Logger().Info(msg, "workflow", cfg.WorkflowName)
return nil, fmt.Errorf("expected user error, got: %w", err)
}

runtime.Logger().Info("Aptos view user error classified as expected", "error", err.Error(), "workflow", cfg.WorkflowName)
return nil, nil
}

func parseSingleStringViewReply(data []byte) (string, error) {
var values []string
if err := json.Unmarshal(data, &values); err != nil {
Expand Down
35 changes: 35 additions & 0 deletions system-tests/tests/smoke/cre/aptos_capability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func aptosDefaultScenarios() []aptosScenario {
return []aptosScenario{
{name: "Aptos Write Read Roundtrip", requiresWrite: true, run: ExecuteAptosWriteReadRoundtripTest},
{name: "Aptos Write Expected Failure", requiresWrite: true, run: ExecuteAptosWriteExpectedFailureTest},
{name: "Aptos View User Error", requiresWrite: false, run: ExecuteAptosViewUserErrorTest},
}
}

Expand Down Expand Up @@ -121,6 +122,11 @@ func resolveAptosScenarios(t *testing.T) []aptosScenario {
requiresWrite: true,
run: ExecuteAptosWriteExpectedFailureTest,
},
"view-user-error": {
name: "Aptos View User Error",
requiresWrite: false,
run: ExecuteAptosViewUserErrorTest,
},
}

parts := strings.Split(raw, ",")
Expand Down Expand Up @@ -274,6 +280,35 @@ func ExecuteAptosReadTest(
lggr.Info().Str("expected_log", expectedLog).Msg("Aptos read capability test passed")
}

// ExecuteAptosViewUserErrorTest deploys the read workflow in user-error mode: it calls View on a
// module that doesn't exist, which the Aptos node rejects with HTTP 400, and asserts the workflow
// receives it as a user-origin capability error rather than a system error.
func ExecuteAptosViewUserErrorTest(
t *testing.T,
tenv *configuration.TestEnvironment,
aptosChain blockchains.Blockchain,
userLogsCh <-chan *workflowevents.UserLogs,
baseMessageCh <-chan *commonevents.BaseMessage,
) {
lggr := framework.L

ensureAptosLedgerVersionPositive(t, aptosChain)

workflowName := uniqueAptosWorkflowName("aptos-view-user-error-workflow")
workflowConfig := t_helpers.AptosReadWorkflowConfig{
ChainSelector: aptosChain.ChainSelector(),
WorkflowName: workflowName,
ExpectUserError: true,
}

const workflowFileLocation = "./aptos/aptosread/main.go"
workflowID := t_helpers.CompileAndDeployWorkflow(t, tenv, lggr, workflowName, &workflowConfig, workflowFileLocation)

expectedLog := "Aptos view user error classified as expected"
t_helpers.WatchWorkflowLogs(t, lggr, userLogsCh, baseMessageCh, t_helpers.WorkflowEngineInitErrorLog, expectedLog, aptosWorkflowTimeout, t_helpers.WithUserLogWorkflowID(workflowID))
lggr.Info().Str("expected_log", expectedLog).Msg("Aptos view user error classification test passed")
}

// The local Aptos devnet can legitimately remain at ledger version 0 until the
// first Aptos transaction lands, which makes the read capability reject the
// consensus height before the workflow has a chance to execute.
Expand Down
1 change: 1 addition & 0 deletions system-tests/tests/test-helpers/t_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ type AptosReadWorkflowConfig struct {
ChainSelector uint64 `yaml:"chainSelector"`
WorkflowName string `yaml:"workflowName"`
ExpectedCoinName string `yaml:"expectedCoinName"`
ExpectUserError bool `yaml:"expectUserError"`
}

// StellarReadWorkflowConfig mirrors the fields of the stellarread workflow's
Expand Down
Loading