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
29 changes: 27 additions & 2 deletions .github/actions/walletkit-build-and-maestro/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ inputs:
wallet-private-key:
description: 'Test wallet private key (sets ENV_TEST_PRIVATE_KEY).'
required: true
polygon-rpc-url:
description: |
Polygon RPC URL used by the Permit2 allowance-reset step. Defaults to the
public endpoint. USDT on Polygon is a plain ERC-20 (no EIP-3009/2612), so
WC Pay uses the Permit2 approve path — this lets the reset revoke that
allowance so each run re-exercises the approve step. Default avoids
polygon-rpc.com, which gates requests (HTTP 401 "tenant disabled") in CI.
required: false
default: 'https://polygon-bor-rpc.publicnode.com'
merchant-api-key-single-nokyc:
description: 'Partner API key for the single-option no-KYC merchant (WPAY_CUSTOMER_KEY_SINGLE_NOKYC).'
required: true
Expand Down Expand Up @@ -399,9 +408,10 @@ runs:
sudo udevadm trigger --name-match=kvm

# --- Common: Maestro setup + run ---
# Pinned to WalletConnect/actions master
# TEMP: pinned to the WalletConnect/actions PR #97 head (adds pay_usdt_polygon).
# Re-pin to the squash-merge commit on master once #97 lands.
- name: Copy shared Pay test flows
uses: WalletConnect/actions/maestro/pay-tests@dd7c71c7292ed568c0ce6c4160ad3c04863db3a0
uses: WalletConnect/actions/maestro/pay-tests@d07c1f8a83dde5c52b7c8649a6814f98ba716b6b

- name: Install Maestro
uses: WalletConnect/actions/maestro/setup@dd7c71c7292ed568c0ce6c4160ad3c04863db3a0
Expand Down Expand Up @@ -562,6 +572,21 @@ runs:
# download+rename step if both attempts' artifacts are needed.
overwrite: true

# Reset the USDT Permit2 allowance back to 0 so the next pay_usdt_polygon run
# re-exercises the approve step. Runs even when the suite failed (if: always())
# so a mid-flow failure doesn't leave the allowance set. Uses the shared
# permit2-reset action (the private key goes via env, never the CLI).
# continue-on-error so a reset hiccup can't fail an otherwise-green run.
- name: Reset USDT Permit2 allowance (Polygon)
if: always() && contains(inputs.maestro-tags, 'pay')
continue-on-error: true
uses: WalletConnect/actions/maestro/permit2-reset@d07c1f8a83dde5c52b7c8649a6814f98ba716b6b
with:
chain-id: eip155:137
rpc-url: ${{ inputs.polygon-rpc-url }}
token-address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F'
private-key: ${{ inputs.wallet-private-key }}

- name: Log Maestro outcome
if: always()
shell: bash
Expand Down
95 changes: 95 additions & 0 deletions .github/workflows/e2e-balance-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ env:
BASE_RPC: 'https://mainnet.base.org'
OP_USDC: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85'
OP_RPC: 'https://mainnet.optimism.io'
POLYGON_USDT: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F'
# polygon-rpc.com gates requests (HTTP 401 "tenant disabled") in CI; use publicnode.
POLYGON_RPC: 'https://polygon-bor-rpc.publicnode.com'

jobs:
check-balance:
Expand Down Expand Up @@ -115,3 +118,95 @@ jobs:
env.SLACK_FAUCETBOT_WEBHOOK_URL == ''
run: |
echo "::warning::SLACK_FAUCETBOT_WEBHOOK_URL not configured, skipping Optimism USDC alert"

# USDT on Polygon funds the pay_usdt_polygon Permit2 flow (the actual payment).
- name: Check USDT balance on Polygon
id: poly_usdt_balance
run: |
BALANCE=$(cast call --rpc-url "$POLYGON_RPC" "$POLYGON_USDT" \
"balanceOf(address)(uint256)" \
"${{ vars.TEST_WALLET_ADDRESS }}" | sed 's/\[.*\]//' | tr -d '[:space:]')
echo "balance=$BALANCE" >> $GITHUB_OUTPUT
BALANCE_HUMAN=$(echo "scale=2; $BALANCE / 1000000" | bc)
echo "USDT0 on Polygon: $BALANCE_HUMAN ($BALANCE raw)"
Comment thread
ignaciosantise marked this conversation as resolved.

- name: Prepare USDT on Polygon alert
id: poly_usdt_alert
run: |
BALANCE="${{ steps.poly_usdt_balance.outputs.balance }}"
THRESHOLD="${{ vars.USDT_POLYGON_THRESHOLD_UNITS || '1000000' }}"
if [ "$BALANCE" -lt "$THRESHOLD" ]; then
BALANCE_HUMAN=$(echo "scale=2; $BALANCE / 1000000" | bc)
THRESHOLD_HUMAN=$(echo "scale=2; $THRESHOLD / 1000000" | bc)
ALERT_TEXT="[request] Can i have ${THRESHOLD_HUMAN} USDT0 on Polygon in wallet: \
${{ vars.TEST_WALLET_ADDRESS }}"
Comment thread
ignaciosantise marked this conversation as resolved.
echo "should_alert=true" >> "$GITHUB_OUTPUT"
echo "text=$ALERT_TEXT" >> "$GITHUB_OUTPUT"
echo "::warning::$ALERT_TEXT"
fi

- name: Send Slack alert (USDT on Polygon)
if: |
steps.poly_usdt_alert.outputs.should_alert == 'true' &&
env.SLACK_FAUCETBOT_WEBHOOK_URL != ''
uses: slackapi/slack-github-action@b0fa283ad8fea605de13dc3f449259339835fc52 # v2.1.0
with:
webhook: ${{ env.SLACK_FAUCETBOT_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
{
"text": "${{ steps.poly_usdt_alert.outputs.text }}"
}

- name: Skip Slack alert (USDT on Polygon - no webhook)
if: |
steps.poly_usdt_alert.outputs.should_alert == 'true' &&
env.SLACK_FAUCETBOT_WEBHOOK_URL == ''
run: |
echo "::warning::SLACK_FAUCETBOT_WEBHOOK_URL not configured, skipping Polygon USDT alert"

# Native POL gas on Polygon: needed for both the payment txs (approve + pay)
# and the post-test Permit2 allowance-reset tx.
- name: Check POL gas balance on Polygon
id: poly_pol_balance
run: |
BALANCE=$(cast balance --rpc-url "$POLYGON_RPC" "${{ vars.TEST_WALLET_ADDRESS }}" | tr -d '[:space:]')
echo "balance=$BALANCE" >> $GITHUB_OUTPUT
BALANCE_HUMAN=$(echo "scale=6; $BALANCE / 1000000000000000000" | bc)
echo "POL on Polygon: $BALANCE_HUMAN ($BALANCE wei)"

- name: Prepare Polygon POL gas alert
id: poly_pol_alert
run: |
BALANCE="${{ steps.poly_pol_balance.outputs.balance }}"
THRESHOLD="${{ vars.POLYGON_POL_THRESHOLD_WEI || '1000000000000000000' }}"
# Use bc for the comparison: wei values overflow shell arithmetic.
if [ "$(echo "$BALANCE < $THRESHOLD" | bc)" -eq 1 ]; then
BALANCE_HUMAN=$(echo "scale=6; $BALANCE / 1000000000000000000" | bc)
THRESHOLD_HUMAN=$(echo "scale=6; $THRESHOLD / 1000000000000000000" | bc)
ALERT_TEXT="[request] Can i have ${THRESHOLD_HUMAN} POL (gas) on Polygon in wallet: \
${{ vars.TEST_WALLET_ADDRESS }} (currently ${BALANCE_HUMAN})"
echo "should_alert=true" >> "$GITHUB_OUTPUT"
echo "text=$ALERT_TEXT" >> "$GITHUB_OUTPUT"
echo "::warning::$ALERT_TEXT"
fi

- name: Send Slack alert (Polygon POL gas)
if: |
steps.poly_pol_alert.outputs.should_alert == 'true' &&
env.SLACK_FAUCETBOT_WEBHOOK_URL != ''
uses: slackapi/slack-github-action@b0fa283ad8fea605de13dc3f449259339835fc52 # v2.1.0
with:
webhook: ${{ env.SLACK_FAUCETBOT_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
{
"text": "${{ steps.poly_pol_alert.outputs.text }}"
}

- name: Skip Slack alert (Polygon POL gas - no webhook)
if: |
steps.poly_pol_alert.outputs.should_alert == 'true' &&
env.SLACK_FAUCETBOT_WEBHOOK_URL == ''
run: |
echo "::warning::SLACK_FAUCETBOT_WEBHOOK_URL not configured, skipping Polygon POL gas alert"
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,11 @@ fastlane/report.xml
.maestro/pay_*.yaml
.maestro/flows/pay_*.yaml
.maestro/scripts/

# Maestro local run artifacts
*.mp4
usdt-permit2-approve-setup.png

# Downloaded by scripts/setup-maestro-pay-tests.sh from WalletConnect/actions
# (canonical source: maestro/permit2-reset). Used locally via `yarn permit2:revoke`.
wallets/rn_cli_wallet/scripts/revoke-permit2-approval.js
15 changes: 15 additions & 0 deletions scripts/setup-maestro-pay-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,22 @@ cp "$SRC_DIR"/flows/pay_*.yaml "$TARGET_DIR/flows/"
mkdir -p "$TARGET_DIR/scripts"
cp "$SRC_DIR"/scripts/*.js "$TARGET_DIR/scripts/"

# Also fetch the canonical Permit2 reset helper so it can be run locally via
# `yarn permit2:revoke` for manual testing. The committed source of truth is the
# actions repo (maestro/permit2-reset); this copy is gitignored in the wallet.
WALLET_SCRIPTS_DIR="$ROOT_DIR/wallets/rn_cli_wallet/scripts"
REVOKE_SRC="$(find "$TMP_DIR" -type f -path '*/maestro/permit2-reset/revoke-permit2-approval.js' | head -1)"
if [ -n "$REVOKE_SRC" ]; then
mkdir -p "$WALLET_SCRIPTS_DIR"
cp "$REVOKE_SRC" "$WALLET_SCRIPTS_DIR/revoke-permit2-approval.js"
fi

echo "Pay test flows copied to $TARGET_DIR/"
echo " $(count_matches "$TARGET_DIR" 'pay_*.yaml') root flows"
echo " $(count_matches "$TARGET_DIR/flows" 'pay_*.yaml') sub-flows"
echo " $(count_matches "$TARGET_DIR/scripts" '*.js') scripts"
if [ -n "$REVOKE_SRC" ]; then
echo " permit2 reset helper -> wallets/rn_cli_wallet/scripts/ (run: yarn permit2:revoke)"
else
echo " (permit2-reset helper not found in $REPO@$REF; skipped)"
fi
4 changes: 4 additions & 0 deletions wallets/rn_cli_wallet/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ The app uses standardized `testID` props for Maestro E2E testing. These IDs are
- `.maestro/pay_single_option_nokyc.yaml`: Single payment option, no KYC — goes straight to review screen
- `.maestro/pay_multiple_options_nokyc.yaml`: Multiple payment options, no KYC — option selection then review
- `.maestro/pay_multiple_options_kyc.yaml`: Multiple payment options with KYC — option selection, webview KYC flow, then review
- `.maestro/pay_usdt_polygon.yaml`: USDT on Polygon — a plain ERC-20 (no EIP-3009/2612), so WC Pay uses the Permit2 path: the wallet sends an `approve` (allowance) tx then the payment tx. Best-effort observes the setup step via the `pay-loading-setup-note` testID (soft screenshot), then asserts the success screen. The allowance is reset to 0 after the run (see below) so each run re-exercises `approve`. (Note: USDT on Arbitrum is EIP-3009 / signature-based, so it never needs an on-chain approve — Polygon is used precisely because it does.)
- `.maestro/flows/pay_open_and_paste_url.yaml`: Shared sub-flow — opens wallet, pastes payment URL, waits for merchant info
- `.maestro/flows/pay_confirm_and_verify.yaml`: Shared sub-flow — taps Pay, verifies success screen
- `.maestro/scripts/create-payment.js`: Creates a payment via the WalletConnect Pay API (called via `runScript`)
Expand All @@ -204,6 +205,9 @@ When set, the wallet auto-loads this private key on startup (if no stored wallet
### CI Workflow
`.github/workflows/ci_e2e_walletkit.yaml` runs Maestro tests on both iOS (simulator) and Android (emulator). Triggers on PRs/pushes to main when `wallets/rn_cli_wallet/` or `.maestro/` files change.

### Permit2 allowance reset (USDT)
After the suite runs, the composite action (`.github/actions/walletkit-build-and-maestro`) calls the shared `WalletConnect/actions/maestro/permit2-reset` action to reset the USDT-on-Polygon Permit2 allowance back to 0, so `pay_usdt_polygon` always re-exercises the `approve` step. It signs a transaction (so it's a Node step, not a Maestro `runScript`); the private key is passed via env, never the CLI. `.github/workflows/e2e-balance-check.yml` also monitors USDT + POL (gas) on Polygon and pings the faucet bot on Slack when low.

## Development

### Prerequisites
Expand Down
Loading
Loading