Skip to content
Open
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
98 changes: 98 additions & 0 deletions .github/workflows/wallet-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Wallet E2E Integration Test
#
# Deploys an OpenClaw instance with a wallet, funds it on Hoodi,
# sends a transaction, and verifies skills work end-to-end.
#
# Required secrets:
# ANTHROPIC_API_KEY — Anthropic API key for LLM provider
# HOODI_FUNDER_PRIVATE_KEY — hex private key of a pre-funded Hoodi testnet wallet

name: Wallet E2E

on:
# Temporary
push:
branches:
- oisin/integration
workflow_dispatch: {}
schedule:
# Weekly on Monday at 07:00 UTC — catch regressions without burning credits daily.
- cron: '0 7 * * 1'

env:
OBOL_CONFIG_DIR: ${{ github.workspace }}/.workspace/config
OBOL_BIN_DIR: ${{ github.workspace }}/.workspace/bin
OBOL_DATA_DIR: ${{ github.workspace }}/.workspace/data

jobs:
wallet-e2e:
runs-on: ubuntu-latest
timeout-minutes: 25

steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

- name: Set up Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version-file: go.mod

- name: Install k3d
run: |
curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash

- name: Install helmfile + helm-diff
run: |
curl -fsSL https://github.com/helmfile/helmfile/releases/download/v1.2.3/helmfile_1.2.3_linux_amd64.tar.gz \
| tar -xzC /usr/local/bin helmfile
helm plugin install https://github.com/databus23/helm-diff --version v3.14.1

- name: Build obol binary and link dependencies
run: |
mkdir -p .workspace/bin
go build -o .workspace/bin/obol ./cmd/obol
# obol looks for tools in OBOL_BIN_DIR — symlink the globally-installed ones.
for bin in k3d helm helmfile kubectl; do
if command -v "$bin" &>/dev/null && [ ! -e ".workspace/bin/$bin" ]; then
ln -s "$(command -v "$bin")" ".workspace/bin/$bin"
fi
done

- name: Start cluster
run: |
.workspace/bin/obol stack init
.workspace/bin/obol stack up
# Wait for default infrastructure to settle.
sleep 30
.workspace/bin/obol kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=traefik -n traefik --timeout=120s || true
.workspace/bin/obol kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=erpc -n erpc --timeout=120s || true

- name: Run wallet E2E test
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
HOODI_FUNDER_PRIVATE_KEY: ${{ secrets.HOODI_FUNDER_PRIVATE_KEY }}
run: |
go test -tags integration -v -run 'TestIntegration_WalletE2E' \
-timeout 20m ./internal/openclaw/

- name: Collect logs on failure
if: failure()
run: |
echo "=== Pod status ==="
.workspace/bin/obol kubectl get pods -A || true
echo ""
echo "=== Events ==="
.workspace/bin/obol kubectl get events -A --sort-by='.lastTimestamp' | tail -50 || true
echo ""
echo "=== OpenClaw logs ==="
.workspace/bin/obol kubectl logs -n openclaw-test-wallet-e2e deploy/openclaw -c openclaw --tail=50 || true
echo ""
echo "=== Remote-signer logs ==="
.workspace/bin/obol kubectl logs -n openclaw-test-wallet-e2e deploy/remote-signer --tail=50 || true

- name: Tear down cluster
if: always()
run: |
.workspace/bin/obol stack down || true
.workspace/bin/obol stack purge -f || true
Comment on lines 29 to 98

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 18 hours ago

In general, fix this class of issue by explicitly declaring a permissions: block that grants only the minimal required scopes, either at the workflow root (applies to all jobs) or for each job individually. For a typical test-only workflow that just checks out code and runs tests, contents: read is sufficient.

For this specific file .github/workflows/wallet-e2e.yml, the best fix without changing functionality is:

  • Add a workflow-level permissions: block after the on: section (or before jobs:) with contents: read.
  • This ensures the wallet-e2e job has a read-only GITHUB_TOKEN, which is enough for actions/checkout and any implicit token use.
  • No steps in this snippet need write access (no pushes, issue/PR mutations, or releases), so we do not grant any write scopes.

Concretely:

  • Insert:

    permissions:
      contents: read

    between the on: block (ending at line 20) and the env: block (starting at line 22). No imports or additional definitions are required.


Suggested changeset 1
.github/workflows/wallet-e2e.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/wallet-e2e.yml b/.github/workflows/wallet-e2e.yml
--- a/.github/workflows/wallet-e2e.yml
+++ b/.github/workflows/wallet-e2e.yml
@@ -19,6 +19,9 @@
     # Weekly on Monday at 07:00 UTC — catch regressions without burning credits daily.
     - cron: '0 7 * * 1'
 
+permissions:
+  contents: read
+
 env:
   OBOL_CONFIG_DIR: ${{ github.workspace }}/.workspace/config
   OBOL_BIN_DIR: ${{ github.workspace }}/.workspace/bin
EOF
@@ -19,6 +19,9 @@
# Weekly on Monday at 07:00 UTC — catch regressions without burning credits daily.
- cron: '0 7 * * 1'

permissions:
contents: read

env:
OBOL_CONFIG_DIR: ${{ github.workspace }}/.workspace/config
OBOL_BIN_DIR: ${{ github.workspace }}/.workspace/bin
Copilot is powered by AI and may make mistakes. Always verify output.
10 changes: 10 additions & 0 deletions internal/embed/skills/addresses/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,16 @@ Restaking protocol. Both are upgradeable proxies (EIP-1967).

Source: [eigenlayer.xyz](https://docs.eigenlayer.xyz/)

### OBOL Token

The Obol Collective token (ERC-20).

| Network | Address | Status |
|---------|---------|--------|
| Mainnet | `0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7` | ✅ Verified |

Source: [docs.obol.org/community-and-governance/obol-token](https://docs.obol.org/community-and-governance/obol-token)

### Obol Splits — Factory Contracts

Obol's Ethereum Validator Manager and reward splitting contracts. Factory contract pattern. Used with splits.org splitter smart contracts and gnosis SAFEs.
Expand Down
16 changes: 16 additions & 0 deletions internal/openclaw/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,22 @@ func provisionKeystoreToVolume(cfg *config.Config, id, keystoreID string, keysto
return "", fmt.Errorf("write keystore: %w", err)
}

// Chown to the remote-signer's UID/GID (65532 — distroless nonroot).
// This runs on the host before the pod starts. On Linux (including
// k3d's Docker host), this works without root because we own the files.
// On macOS, chown to a non-existent UID requires root but k3d runs
// inside Docker where the volume is accessed by the k3d container's root.
const remoteSignerUID = 65532
const remoteSignerGID = 65532
if err := os.Chown(dir, remoteSignerUID, remoteSignerGID); err != nil {
// Non-fatal: may fail on macOS without sudo. The remote-signer
// chart has a fix-permissions init container as a fallback.
fmt.Printf("Warning: could not chown keystore dir to UID %d: %v\n", remoteSignerUID, err)
}
if err := os.Chown(path, remoteSignerUID, remoteSignerGID); err != nil {
fmt.Printf("Warning: could not chown keystore file to UID %d: %v\n", remoteSignerUID, err)
}

return path, nil
}

Expand Down
Loading
Loading