diff --git a/.github/workflows/test-stellar.yaml b/.github/workflows/test-stellar.yaml new file mode 100644 index 00000000..e8f04434 --- /dev/null +++ b/.github/workflows/test-stellar.yaml @@ -0,0 +1,239 @@ +name: Test Stellar + +on: pull_request + +jobs: + check-relevant-changes: + name: Check for Relevant Changes + runs-on: blacksmith-2vcpu-ubuntu-2204 + outputs: + run_tests: ${{ steps.filter.outputs.stellar == 'true' || steps.filter.outputs.common == 'true' || steps.filter.outputs.github == 'true' }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + stellar: + - 'stellar/**' + common: + - 'common/**' + github: + - '.github/workflows/test-stellar.yaml' + - name: Summarize Changes + run: | + echo "Changes in stellar: ${{ steps.filter.outputs.stellar }}" + echo "Changes in common: ${{ steps.filter.outputs.common }}" + echo "Changes in github: ${{ steps.filter.outputs.github }}" + + test-stellar: + name: Test Stellar + needs: check-relevant-changes + if: ${{ needs.check-relevant-changes.outputs.run_tests == 'true' }} + runs-on: blacksmith-2vcpu-ubuntu-2204 + steps: + # this sets up nested repos: https://github.com/actions/checkout?tab=readme-ov-file#checkout-multiple-repos-nested + # + # axelar-contract-deployments + # - axelar-cgp-soroban + # + # future steps depend on this directory structure + - name: Checkout code + uses: actions/checkout@v4 + + - name: Checkout axelar-cgp-soroban repo + uses: actions/checkout@v4 + with: + repository: axelarnetwork/axelar-cgp-soroban + path: axelar-cgp-soroban + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' # Hardcoded to ensure consistency. + cache: 'npm' + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + shell: bash + run: npm ci + + - name: Install stable toolchain + uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.81.0 + targets: wasm32-unknown-unknown + + # install binary to avoid lengthy compilation process + - name: Install Stellar CLI + shell: bash + run: | + # setup bin/ directory + mkdir bin + cd bin + + # Query latest release from official Stellar repo + URL=$(curl -s https://api.github.com/repos/stellar/stellar-cli/releases/latest | jq -r .assets[].browser_download_url | grep 'stellar.*x86_64-unknown-linux') + + # download + extract binary + wget -q $URL + tar -xzf $(basename $URL) + + echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH + + - name: Setup Stellar local network + run: | + docker pull stellar/quickstart + docker run -d --rm -it \ + -p 8000:8000 \ + --name stellar \ + stellar/quickstart:testing \ + --local \ + --enable-soroban-rpc \ + --protocol-version 22 + + RPC_URL="http://localhost:8000/soroban/rpc" + NETWORK_PASSPHRASE="Standalone Network ; February 2017" + echo "RPC_URL=${RPC_URL}" >> $GITHUB_ENV + echo "NETWORK_PASSPHRASE=${NETWORK_PASSPHRASE}" >> $GITHUB_ENV + + - name: Add as configured network + shell: bash + run: | + stellar network add local \ + --rpc-url "$RPC_URL" \ + --network-passphrase "$NETWORK_PASSPHRASE" + + - name: Prepare local.json + run: | + echo '{ + "chains": { + "stellar": { + "name": "Stellar", + "axelarId": "stellar", + "networkType": "local", + "chainType": "stellar", + "tokenSymbol": "XLM", + "rpc": "http://127.0.0.1:8000/soroban/rpc", + "horizonRpc": "http://127.0.0.1:8000", + "contracts": {} + } + } + }' > ./axelar-chains-config/info/local.json + + - name: Display local.json + run: cat ./axelar-chains-config/info/local.json + + ###### Acquire WASM Contracts ###### + - name: Configure CF credentials + run: | + cd $HOME; mkdir ~/.aws; touch ~/.aws/credentials; touch ~/.aws/config + echo "[default] + aws_access_key_id = ${{ secrets.cf-bucket-access-key-id }} + aws_secret_access_key = ${{ secrets.cf-bucket-secret-access-key }}" > ~/.aws/credentials + echo "[default] + region=auto + output=json" > ~/.aws/config + + - name: Fetch WASM contracts from CF + env: + S3_BUCKET_NAME: ${{ vars.CF_BUCKET_NAME }} + ENDPOINT_URL: ${{ secrets.CF-ENDPOINT-URL }} + CF_BUCKET_ROOT_KEY: ${{ vars.CF_BUCKET_ROOT_KEY }} + run: | + PACKAGE_VERSION=$(cat stellar/version) + CONTRACTS=("axelar_gateway" "axelar_operators" "axelar_gas_service" "interchain_token" "interchain_token_service" "example") + for name in CONTRACTS; do + CF_WASM_BUCKET_ROOT_KEY="${CF_BUCKET_ROOT_KEY}/$name/$PACKAGE_VERSION/wasm" + FILE_KEY=axelar-cgp-soroban-wasm-$name-$PACKAGE_VERSION + aws s3api get-object --bucket $S3_BUCKET_NAME --key "$CF_WASM_BUCKET_ROOT_KEY/$FILE_KEY" --acl public-read --endpoint-url $ENDPOINT_URL + done + + ls + + WASM_DIR=./ + echo "WASM_DIR=${WASM_DIR}" >> $GITHUB_ENV + + - name: Setup Stellar wallet + run: | + stellar keys generate test \ + --rpc-url "$RPC_URL" \ + --network-passphrase "$NETWORK_PASSPHRASE" + + STELLAR_PRIVATE_KEY=$(stellar keys show test) + STELLAR_ADDRESS=$(stellar keys address test) + echo "STELLAR_PRIVATE_KEY=${STELLAR_PRIVATE_KEY}" >> $GITHUB_ENV + echo "STELLAR_ADDRESS=${STELLAR_ADDRESS}" >> $GITHUB_ENV + + - name: Fund Stellar wallet + run: node stellar/faucet --recipient $STELLAR_ADDRESS + + - name: Prepare .env + run: | + echo "PRIVATE_KEY = '$STELLAR_PRIVATE_KEY'" >> .env + echo "ENV = 'local'" >> .env + echo "YES = 'true'" >> .env + + ###### Command: Deploy Contract ###### + - name: Deploy axelar_gateway + run: | + CONTRACT=axelar_gateway + node stellar/deploy-contract deploy $CONTRACT --wasm-path $WASM_DIR/$CONTRACT.optimized.wasm + + - name: Deploy axelar_operators + run: | + CONTRACT=axelar_operators + node stellar/deploy-contract deploy $CONTRACT --wasm-path $WASM_DIR/$CONTRACT.optimized.wasm + + ###### Command: Gateway ###### + # FIXME: + # - name: Gateway Approve + # run: | + # node stellar/gateway approve avalanche 0x32034b47cb29d162d9d803cc405356f4ac0ec07fe847ace431385fe8acf3e6e5-2 0x4F4495243837681061C4743b74B3eEdf548D56A5 wallet 0x1234 + + - name: Gateway Call Contract + run: node stellar/gateway.js call-contract avalanche 0x4F4495243837681061C4743b74B3eEdf548D56A5 0x1234 + + - name: Gateway Rotate Signers + run: | + node stellar/gateway rotate --new-nonce test --signers wallet + node stellar/gateway rotate --new-nonce test2 --current-nonce test --signers wallet + + - name: Upgrade gateway contract + run: | + CONTRACT=axelar_gateway + node stellar/deploy-contract.js upgrade $CONTRACT --wasm-path $WASM_DIR/$CONTRACT.optimized.wasm + + ###### Command: Operators ###### + + - name: Execute is_operator action + run: node stellar/operators.js --action is_operator --args $STELLAR_ADDRESS + + - name: Execute add_operator action + run: node stellar/operators.js --action add_operator --args $STELLAR_ADDRESS + + - name: Execute remove_operator action + run: node stellar/operators.js --action remove_operator --args $STELLAR_ADDRESS + + # TODO: needs gas-service contract + # - name: Execute refund action + # run: node stellar/operators.js --action refund + + # FIXME: find proper way to execute this + # - name: Execute execute action + # run: node stellar/operators.js --action execute --target $STELLAR_ADDRESS --method "is_operator" + + # TODO: currently fails + # - name: is_operator with estimate_cost + # run: node stellar/operators.js --action is_operator --args $STELLAR_ADDRESS --estimate-cost + + ###### Command: Generate Bindings ##### + - name: generate operators bindings + run: | + CONTRACT=axelar_operators + node stellar/generate-bindings.js --wasm-path $WASM_DIR/$CONTRACT.optimized.wasm --contract-id $(jq .chains.stellar.contracts.$CONTRACT.address axelar-chains-config/info/local.json) --output-dir ./stellar/bindings/$CONTRACT + + - name: generate gateway bindings + run: | + CONTRACT=axelar_gateway + node stellar/generate-bindings.js --wasm-path $WASM_DIR/$CONTRACT.optimized.wasm --contract-id $(jq .chains.stellar.contracts.$CONTRACT.address axelar-chains-config/info/local.json) --output-dir ./stellar/bindings/$CONTRACT diff --git a/stellar/generate-bindings.js b/stellar/generate-bindings.js index aa17f6e4..6708b5a2 100644 --- a/stellar/generate-bindings.js +++ b/stellar/generate-bindings.js @@ -37,7 +37,7 @@ function main() { program.action((options) => { const config = loadConfig(options.env); - processCommand(options, config, config.stellar); + processCommand(options, config, config.chains.stellar); }); program.parse(); diff --git a/stellar/utils.js b/stellar/utils.js index df034b46..ba3e9c10 100644 --- a/stellar/utils.js +++ b/stellar/utils.js @@ -25,7 +25,7 @@ const ASSET_TYPE_NATIVE = 'native'; function getNetworkPassphrase(networkType) { switch (networkType) { case 'local': - return Networks.SANDBOX; + return Networks.STANDALONE; case 'futurenet': return Networks.FUTURENET; case 'testnet': @@ -148,7 +148,7 @@ async function sendTransaction(tx, server, action, options = {}) { } async function broadcast(operation, wallet, chain, action, options = {}) { - const server = new rpc.Server(chain.rpc); + const server = new rpc.Server(chain.rpc, { allowHttp: true }); if (options.estimateCost) { const tx = await buildTransaction(operation, server, wallet, chain.networkType, options); @@ -168,8 +168,10 @@ function getAssetCode(balance, chain) { async function getWallet(chain, options) { const keypair = Keypair.fromSecret(options.privateKey); const address = keypair.publicKey(); - const provider = new rpc.Server(chain.rpc); - const horizonServer = new Horizon.Server(chain.horizonRpc); + const provider = new rpc.Server(chain.rpc, { + allowHttp: true, + }); + const horizonServer = new Horizon.Server(chain.horizonRpc, { allowHttp: true }); const balances = await getBalances(horizonServer, address); printInfo('Wallet address', address); diff --git a/stellar/version b/stellar/version new file mode 100644 index 00000000..7da0a952 --- /dev/null +++ b/stellar/version @@ -0,0 +1 @@ +a90ac0b9d2d66533f32df8a9e5e15e483ec59c5d