feat(tvf): collect transaction hashes for stellar_signXDR and stellar_signAndSubmitXDR #182
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Maestro E2E Pay Tests | |
| # "(skip-metrics)" tells the E2E KPI job (WalletConnect/actions) to drop this run. | |
| run-name: ${{ ((github.event_name == 'pull_request' && github.event.pull_request.draft) || (github.event_name == 'workflow_dispatch' && github.ref_name != 'develop')) && format('{0} (skip-metrics)', github.event.pull_request.title || github.ref_name) || '' }} | |
| on: | |
| pull_request: | |
| types: | |
| - opened | |
| - synchronize | |
| - reopened | |
| - ready_for_review | |
| branches: | |
| - develop | |
| - main | |
| schedule: | |
| # Run daily at 04:00 UTC (only on the default branch) | |
| - cron: '0 4 * * *' | |
| workflow_dispatch: {} | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref_name }} | |
| cancel-in-progress: true | |
| jobs: | |
| check-balance: | |
| if: github.event_name != 'pull_request' || github.event.pull_request.draft == false | |
| uses: ./.github/workflows/e2e_balance_check.yml | |
| secrets: inherit | |
| e2e-pay-tests: | |
| needs: check-balance | |
| if: always() && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) | |
| runs-on: macos-latest-xlarge | |
| timeout-minutes: 45 | |
| permissions: | |
| checks: write | |
| actions: read | |
| steps: | |
| - uses: actions/checkout@v3 | |
| - name: Select Xcode 26 (iOS 26 SDK) | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: '26' | |
| # Boot the simulator BEFORE the build (not right before `maestro test`). | |
| # A never-booted device posts a one-time "Ready for Apple Intelligence" | |
| # follow-up notification a few minutes after its first boot; when the sim | |
| # was booted seconds before the tests, that banner landed ~8s into the | |
| # first flow, covering the button Maestro was about to tap. Booting early | |
| # lets it fire and auto-dismiss during the ~10 min build instead. | |
| - name: Boot iOS simulator | |
| run: | | |
| # Pick whatever iPhone simulator the runner actually has, so this | |
| # doesn't break each time the Xcode/runner image bumps the model. | |
| # Single awk pass: pull the UDID from the first available iPhone row. | |
| # awk exits 0 even when nothing matches (so the check below stays | |
| # reachable under `set -eo pipefail`), `exit` avoids a head/SIGPIPE | |
| # footgun, and it tolerates parens in the device name (e.g. SE). | |
| SIMULATOR_UDID=$(xcrun simctl list devices available \ | |
| | awk '/iPhone/ { if (match($0, /[0-9A-Fa-f-]{36}/)) { print substr($0, RSTART, RLENGTH); exit } }') | |
| if [ -z "$SIMULATOR_UDID" ]; then | |
| echo "ERROR: no available iPhone simulator found" | |
| xcrun simctl list devices available | |
| exit 1 | |
| fi | |
| echo "Using simulator: $SIMULATOR_UDID" | |
| xcrun simctl boot "$SIMULATOR_UDID" 2>/dev/null || true | |
| xcrun simctl bootstatus "$SIMULATOR_UDID" | |
| # Belt and suspenders for the same banner: iOS stamps this key when it | |
| # posts the follow-up (verified against a sim's CoreFollowUp items.db — | |
| # the item's creationDate matches this key to the second). Pre-seeding | |
| # it marks the notification as already shown, covering runs where the | |
| # build finishes (warm SPM cache) before the banner would have fired. | |
| # Best-effort: booting early is the primary defense, so a runner image | |
| # where this domain isn't writable must not fail the whole run. | |
| xcrun simctl spawn "$SIMULATOR_UDID" defaults write \ | |
| com.apple.generativeexperiences.corefollowup \ | |
| DateOfLastAppleIntelligenceReadinessCFU -date "$(date -u '+%Y-%m-%d %H:%M:%S +0000')" \ | |
| || echo "WARNING: could not pre-seed Apple Intelligence CFU timestamp (non-fatal)" | |
| - uses: actions/cache@v3 | |
| with: | |
| path: | | |
| **/SourcePackagesCache | |
| key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }} | |
| - name: Build WalletApp for simulator (test mode) | |
| id: build | |
| run: | | |
| set -o pipefail && env NSUnbufferedIO=YES \ | |
| xcodebuild \ | |
| -project "Example/ExampleApp.xcodeproj" \ | |
| -scheme "WalletApp" \ | |
| -destination "generic/platform=iOS Simulator" \ | |
| -derivedDataPath DerivedDataCache \ | |
| -clonedSourcePackagesDirPath ../SourcePackagesCache \ | |
| RELAY_HOST='relay.walletconnect.com' \ | |
| PROJECT_ID='${{ secrets.PROJECT_ID }}' \ | |
| TEST_WALLET_PRIVATE_KEY='${{ secrets.TEST_WALLET_PRIVATE_KEY }}' \ | |
| SWIFT_ACTIVE_COMPILATION_CONDITIONS='$(inherited) ENABLE_TEST_MODE' \ | |
| build \ | |
| | xcbeautify | |
| - name: Copy shared Pay test flows | |
| uses: WalletConnect/actions/maestro/pay-tests@4be7c0112f9651fc63b18c137650b75d2fc9b200 | |
| - name: Install Maestro | |
| uses: WalletConnect/actions/maestro/setup@4be7c0112f9651fc63b18c137650b75d2fc9b200 | |
| with: | |
| version: '2.4.0' | |
| - name: Install app on simulator | |
| run: | | |
| APP_PATH=$(find DerivedDataCache -name "WalletApp.app" -path "*/Debug-iphonesimulator/*" | head -1) | |
| if [ -z "$APP_PATH" ]; then | |
| echo "ERROR: WalletApp.app not found in DerivedDataCache" | |
| find DerivedDataCache -name "*.app" -path "*/Debug-iphonesimulator/*" | |
| exit 1 | |
| fi | |
| echo "Installing: $APP_PATH" | |
| xcrun simctl install booted "$APP_PATH" | |
| - name: Run Maestro Pay E2E tests | |
| id: maestro | |
| run: | | |
| maestro test \ | |
| --env APP_ID=com.walletconnect.walletapp \ | |
| --env WPAY_CUSTOMER_KEY_SINGLE_NOKYC=${{ secrets.WPAY_CUSTOMER_KEY_SINGLE_NOKYC }} \ | |
| --env WPAY_MERCHANT_ID_SINGLE_NOKYC=${{ secrets.WPAY_MERCHANT_ID_SINGLE_NOKYC }} \ | |
| --env WPAY_CUSTOMER_KEY_MULTI_NOKYC=${{ secrets.WPAY_CUSTOMER_KEY_MULTI_NOKYC }} \ | |
| --env WPAY_MERCHANT_ID_MULTI_NOKYC=${{ secrets.WPAY_MERCHANT_ID_MULTI_NOKYC }} \ | |
| --env WPAY_CUSTOMER_KEY_MULTI_KYC=${{ secrets.WPAY_CUSTOMER_KEY_MULTI_KYC }} \ | |
| --env WPAY_MERCHANT_ID_MULTI_KYC=${{ secrets.WPAY_MERCHANT_ID_MULTI_KYC }} \ | |
| --include-tags pay \ | |
| --test-output-dir debug-artifacts/maestro-output \ | |
| .maestro/ | |
| # Reset the USDT Permit2 allowance back to 0 so the next pay_usdt_polygon run | |
| # re-exercises the on-chain `approve` step. Runs even when the suite failed | |
| # (if: always()) so a mid-flow failure can't leave the allowance set. | |
| # continue-on-error so a reset hiccup can't fail an otherwise-green run. | |
| # It signs a transaction, so it's a Node step (not a Maestro runScript); the | |
| # private key goes via env, never the CLI. | |
| - name: Reset USDT Permit2 allowance (Polygon) | |
| if: always() | |
| continue-on-error: true | |
| uses: WalletConnect/actions/maestro/permit2-reset@4be7c0112f9651fc63b18c137650b75d2fc9b200 | |
| with: | |
| chain-id: eip155:137 | |
| # polygon-rpc.com gates requests (HTTP 401 "tenant disabled") in CI; use publicnode. | |
| rpc-url: https://polygon-bor-rpc.publicnode.com | |
| token-address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F' | |
| private-key: ${{ secrets.TEST_WALLET_PRIVATE_KEY }} | |
| - name: Capture simulator logs | |
| if: always() | |
| run: | | |
| xcrun simctl spawn booted log collect --output debug-artifacts/sim-logs.logarchive 2>/dev/null || true | |
| - name: Upload debug artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: maestro-pay-test-artifacts | |
| path: | | |
| debug-artifacts/**/*.png | |
| debug-artifacts/**/*.jpg | |
| debug-artifacts/**/*.jpeg | |
| debug-artifacts/**/*.mp4 | |
| debug-artifacts/**/*.mov | |
| debug-artifacts/**/*.webm | |
| debug-artifacts/**/*.gif | |
| debug-artifacts/sim-logs.logarchive | |
| retention-days: 14 | |
| if-no-files-found: ignore | |
| - name: Send Slack notification | |
| if: failure() | |
| uses: slackapi/slack-github-action@b0fa283ad8fea605de13dc3f449259339835fc52 # v2.1.0 | |
| with: | |
| webhook: ${{ secrets.SLACK_WEBHOOK_URL }} | |
| webhook-type: incoming-webhook | |
| payload: | | |
| { | |
| "text": "E2E Test Report - iOS - Pay", | |
| "blocks": [ | |
| { | |
| "type": "header", | |
| "text": { "type": "plain_text", "text": "🧪 E2E Test Report - iOS (pay)" } | |
| }, | |
| { | |
| "type": "section", | |
| "fields": [ | |
| { "type": "mrkdwn", "text": "*Project:*\n`Reown Swift`" }, | |
| { "type": "mrkdwn", "text": "*Platform:*\n`iOS`" }, | |
| { "type": "mrkdwn", "text": "*Branch:*\n`${{ github.ref_name }}`" }, | |
| { "type": "mrkdwn", "text": "*Trigger:*\n`${{ github.event_name }}`" } | |
| ] | |
| }, | |
| { | |
| "type": "section", | |
| "fields": [ | |
| { "type": "mrkdwn", "text": "*Build:*\n`${{ steps.build.outcome == 'success' && '✅ Success' || '❌ Failed' }}`" }, | |
| { "type": "mrkdwn", "text": "*Maestro Tests:*\n`${{ steps.maestro.outcome == 'success' && '✅ Passed' || '❌ Failed' }}`" }, | |
| { "type": "mrkdwn", "text": "*Overall Status:*\n`${{ job.status == 'success' && '✅ Success' || '❌ Failed' }}`" } | |
| ] | |
| }, | |
| { | |
| "type": "actions", | |
| "elements": [ | |
| { | |
| "type": "button", | |
| "text": { "type": "plain_text", "text": "View Workflow Run" }, | |
| "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| }, | |
| { | |
| "type": "button", | |
| "text": { "type": "plain_text", "text": "Download Artifacts" }, | |
| "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}#artifacts" | |
| } | |
| ] | |
| } | |
| ] | |
| } |