Browse Source

ci: switch from ganache to anvil

Evan Gray 1 year ago
parent
commit
77b4ddc812
36 changed files with 352 additions and 422 deletions
  1. 1 2
      .github/workflows/build.yml
  2. 17 5
      DEVELOP.md
  3. 2 2
      Tiltfile
  4. 7 16
      devnet/eth-devnet.yaml
  5. 7 16
      devnet/eth-devnet2.yaml
  6. 1 0
      ethereum/Dockerfile
  7. 0 6
      ethereum/copy-from-container.sh
  8. 0 36
      ethereum/mine.js
  9. 16 9
      node/pkg/watchers/evm/blocks_by_timestamp.go
  10. 7 7
      node/pkg/watchers/evm/blocks_by_timestamp_test.go
  11. 1 2
      node/pkg/watchers/evm/watcher.go
  12. 10 0
      sdk/js-query/ci-config.js
  13. 29 32
      sdk/js-query/src/query/ethCall.test.ts
  14. 25 0
      sdk/js/ci-config.js
  15. 1 1
      sdk/js/jest.config.json
  16. 4 4
      sdk/js/package.json
  17. 0 2
      sdk/js/src/algorand/__tests__/unit.ts
  18. 1 3
      sdk/js/src/bridge/__tests__/wormhole_ibc_e2e.ts
  19. 4 4
      sdk/js/src/nft_bridge/__tests__/aptos-integration.ts
  20. 5 17
      sdk/js/src/nft_bridge/__tests__/integration.ts
  21. 3 1
      sdk/js/src/nft_bridge/__tests__/utils/consts.ts
  22. 97 82
      sdk/js/src/relayer/__tests__/wormhole_relayer.ts
  23. 17 17
      sdk/js/src/token_bridge/__tests__/algorand-integration.ts
  24. 8 17
      sdk/js/src/token_bridge/__tests__/aptos-integration.ts
  25. 12 12
      sdk/js/src/token_bridge/__tests__/eth-integration.ts
  26. 11 15
      sdk/js/src/token_bridge/__tests__/near-integration.ts
  27. 8 16
      sdk/js/src/token_bridge/__tests__/solana-integration.ts
  28. 4 22
      sdk/js/src/token_bridge/__tests__/sui-integration.ts
  29. 14 21
      sdk/js/src/token_bridge/__tests__/terra-integration.ts
  30. 5 7
      sdk/js/src/token_bridge/__tests__/terra2-integration.ts
  31. 3 4
      sdk/js/src/token_bridge/__tests__/utils/consts.ts
  32. 11 40
      wormchain/contracts/tools/__tests__/test_accountant.ts
  33. 1 1
      wormchain/contracts/tools/__tests__/test_ntt_accountant.ts
  34. 18 0
      wormchain/contracts/tools/ci-config.js
  35. 2 2
      wormchain/contracts/tools/package.json
  36. 0 1
      wormchain/ts-sdk/src/core/wallet.ts

+ 1 - 2
.github/workflows/build.yml

@@ -34,8 +34,7 @@ jobs:
           kubectl config set-context ci --namespace=$DEPLOY_NS
           kubectl config use-context ci
 
-      # temporarily set --guardiand_loglevel=info to debug https://github.com/wormhole-foundation/wormhole/issues/3052
-      - run: tilt ci --timeout 45m0s -- --ci --namespace=$DEPLOY_NS --num=2 --guardiand_loglevel=info
+      - run: tilt ci --timeout 45m0s -- --ci --namespace=$DEPLOY_NS --num=2
         timeout-minutes: 60
 
       # Clean up k8s resources

+ 17 - 5
DEVELOP.md

@@ -37,7 +37,7 @@ Launch the devnet:
 
     tilt up
 
-By default this runs a network consisting of one guardian, two ganache (Eth) chains, a Solana test validator, an Algorand sandbox, and LocalTerra for both Terra Classic and Terra 2. If you want to work on non-consensus parts of the code, running with a single guardian is easiest since you won't have to wait for k8s to restart all pods. See the usage guide below for arguments to customize the tilt network.
+By default this runs a network consisting of one guardian, two anvil (Eth) chains, a Solana test validator, an Algorand sandbox, and LocalTerra for both Terra Classic and Terra 2. If you want to work on non-consensus parts of the code, running with a single guardian is easiest since you won't have to wait for k8s to restart all pods. See the usage guide below for arguments to customize the tilt network.
 
 ## Usage
 
@@ -140,28 +140,40 @@ To re-generate these files run `rm -rf node/pkg/proto && docker build --target g
 
 ### Call gRPC services
 
-<!-- cspell:disable-next-line -->
+<!-- cspell:disable -->
+
     tools/bin/grpcurl -protoset <(tools/bin/buf build -o -) -plaintext localhost:7072 spy.v1.SpyRPCService/SubscribeSignedVAA
 
+<!-- cspell:enable -->
+
 With parameters (using proto json encoding):
 
-<!-- cspell:disable-next-line -->
+<!-- cspell:disable -->
+
     tools/bin/grpcurl -protoset <(tools/bin/buf build -o -) \
         -d '{"filters": [{"emitter_filter": {"emitter_address": "574108aed69daf7e625a361864b1f74d13702f2ca56de9660e566d1d8691848d", "chain_id": "CHAIN_ID_SOLANA"}}]}' \
         -plaintext localhost:7072 spy.v1.SpyRPCService/SubscribeSignedVAA
 
+<!-- cspell:enable -->
+
 ### Post messages
 
 To Solana:
 
-<!-- cspell:disable-next-line -->
+<!-- cspell:disable -->
+
     kubectl exec solana-devnet-0 -c setup -- client post-message Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o 1 confirmed ffff
 
+<!-- cspell:enable -->
+
 To Solana as CPI instruction:
 
-<!-- cspell:disable-next-line -->
+<!-- cspell:disable -->
+
     kubectl exec solana-devnet-0 -c setup -- client post-message --proxy CP1co2QMMoDPbsmV7PGcUTLFwyhgCgTXt25gLQ5LewE1 Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o 1 confirmed ffff
 
+<!-- cspell:enable -->
+
 ### Observation Requests
 
     kubectl exec -it guardian-0 -- /guardiand admin send-observation-request --socket /tmp/admin.sock 1 4636d8f7593c78a5092bed13dec765cc705752653db5eb1498168c92345cd389

+ 2 - 2
Tiltfile

@@ -534,7 +534,7 @@ k8s_yaml_with_ns("devnet/eth-devnet.yaml")
 k8s_resource(
     "eth-devnet",
     port_forwards = [
-        port_forward(8545, name = "Ganache RPC [:8545]", host = webHost),
+        port_forward(8545, name = "Anvil RPC [:8545]", host = webHost),
     ],
     labels = ["evm"],
     trigger_mode = trigger_mode,
@@ -546,7 +546,7 @@ if evm2:
     k8s_resource(
         "eth-devnet2",
         port_forwards = [
-            port_forward(8546, name = "Ganache RPC [:8546]", host = webHost),
+            port_forward(8546, 8545, name = "Anvil RPC [:8546]", host = webHost),
         ],
         labels = ["evm"],
         trigger_mode = trigger_mode,

+ 7 - 16
devnet/eth-devnet.yaml

@@ -31,19 +31,16 @@ spec:
     spec:
       terminationGracePeriodSeconds: 1
       containers:
-        - name: ganache
+        - name: anvil
           image: eth-node
           command:
-            - npx
-            - ganache-cli
-            - --logging.quiet
-            - --wallet.defaultBalance=10000
-            - --wallet.deterministic
-            - --chain.time="1970-01-01T00:00:00+00:00"
+            - anvil
+            - --silent
+            - --mnemonic=myth like bonus scare over problem client lizard pioneer submit female collect
+            - --block-time=1
             - --host=0.0.0.0
-            - --wallet.totalAccounts=13
-            - --chain.chainId=1337
-            - --chain.asyncRequestProcessing=false
+            - --accounts=13
+            - --chain-id=1337
           ports:
             - containerPort: 8545
               name: rpc
@@ -64,11 +61,5 @@ spec:
             initialDelaySeconds: 90
             tcpSocket:
               port: 2000
-        - name: mine
-          image: eth-node
-          command:
-            - /bin/sh
-            - -c
-            - "cd ../../ethereum && npx truffle exec mine.js"
 ---
 

+ 7 - 16
devnet/eth-devnet2.yaml

@@ -32,19 +32,16 @@ spec:
     spec:
       terminationGracePeriodSeconds: 1
       containers:
-        - name: ganache
+        - name: anvil
           image: eth-node
           command:
-            - npx
-            - ganache-cli
-            - --logging.quiet
-            - --wallet.defaultBalance=10000
-            - --wallet.deterministic
-            - --chain.time="1970-01-01T00:00:00+00:00"
+            - anvil
+            - --silent
+            - --mnemonic=myth like bonus scare over problem client lizard pioneer submit female collect
+            - --block-time=1
             - --host=0.0.0.0
-            - --wallet.totalAccounts=13
-            - --chain.chainId=1397
-            - --chain.asyncRequestProcessing=false
+            - --accounts=13
+            - --chain-id=1397
           ports:
             - containerPort: 8545
               name: rpc
@@ -65,9 +62,3 @@ spec:
             initialDelaySeconds: 90
             tcpSocket:
               port: 2000
-        - name: mine
-          image: eth-node
-          command:
-            - /bin/sh
-            - -c
-            - "cd ../../ethereum && npx truffle exec mine.js"

+ 1 - 0
ethereum/Dockerfile

@@ -14,6 +14,7 @@ RUN $HOME/.foundry/bin/foundryup
 RUN ls $HOME/.foundry/bin
 
 # Run as user, otherwise, npx explodes.
+RUN mv /root/.foundry/bin/anvil /bin/anvil
 RUN mv /root/.foundry/bin/forge /bin/forge
 USER 1000
 

+ 0 - 6
ethereum/copy-from-container.sh

@@ -1,6 +0,0 @@
-#!/usr/bin/env bash
-# This script copies package{-lock}.json from a running container.
-set -e
-
-kubectl cp -c ganache eth-devnet-0:package.json package.json
-kubectl cp -c ganache eth-devnet-0:package-lock.json package-lock.json

+ 0 - 36
ethereum/mine.js

@@ -1,36 +0,0 @@
-/*
-    This script advances Ganache network state. It runs as a sidecar pod alongside the devnet and
-    ensures that manual token transfers triggered through the web UI will be able to be confirmed.
- */
-
-advanceBlock = () => {
-    return new Promise((resolve, reject) => {
-        web3.currentProvider.send({
-            jsonrpc: "2.0",
-            method: "evm_mine",
-            id: new Date().getTime()
-        }, (err, result) => {
-            if (err) {
-                return reject(err);
-            }
-            const newBlockHash = web3.eth.getBlock('latest').hash;
-
-            return resolve(newBlockHash)
-        });
-    });
-}
-
-function sleep(ms) {
-    return new Promise(resolve => setTimeout(resolve, ms));
-}
-
-module.exports = function(callback) {
-    const fn = async () => {
-        while (true) {
-            await advanceBlock();
-            await sleep(1000);
-        }
-    }
-
-    fn().catch(reason => console.error(reason))
-}

+ 16 - 9
node/pkg/watchers/evm/blocks_by_timestamp.go

@@ -19,6 +19,9 @@ type (
 		// maxCacheSize is used to trim the cache.
 		maxCacheSize int
 
+		// unsafeDevMode is used to suppress warnings in dev mode.
+		unsafeDevMode bool
+
 		// mutex is used to protect the cache.
 		mutex sync.Mutex
 	}
@@ -32,10 +35,11 @@ type (
 )
 
 // NewBlocksByTimestamp creates an empty cache of blocks by timestamp.
-func NewBlocksByTimestamp(maxCacheSize int) *BlocksByTimestamp {
+func NewBlocksByTimestamp(maxCacheSize int, unsafeDevMode bool) *BlocksByTimestamp {
 	return &BlocksByTimestamp{
-		cache:        Blocks{},
-		maxCacheSize: maxCacheSize,
+		cache:         Blocks{},
+		maxCacheSize:  maxCacheSize,
+		unsafeDevMode: unsafeDevMode,
 	}
 }
 
@@ -55,12 +59,15 @@ func (bts *BlocksByTimestamp) AddLatest(logger *zap.Logger, timestamp uint64, bl
 			}
 		}
 
-		logger.Warn("rollback detected in timestamp cache",
-			zap.Uint64("oldLatestBlockNum", bts.cache[l-1].BlockNum),
-			zap.Uint64("oldLatestTimestamp", bts.cache[l-1].Timestamp),
-			zap.Uint64("newLatestBlockNum", blockNum),
-			zap.Uint64("newLatestTimestamp", timestamp),
-		)
+		// Anvil trips this when using `anvil_mine`
+		if !bts.unsafeDevMode {
+			logger.Warn("rollback detected in timestamp cache",
+				zap.Uint64("oldLatestBlockNum", bts.cache[l-1].BlockNum),
+				zap.Uint64("oldLatestTimestamp", bts.cache[l-1].Timestamp),
+				zap.Uint64("newLatestBlockNum", blockNum),
+				zap.Uint64("newLatestTimestamp", timestamp),
+			)
+		}
 		bts.cache = bts.cache[:idx+1]
 	}
 

+ 7 - 7
node/pkg/watchers/evm/blocks_by_timestamp_test.go

@@ -24,7 +24,7 @@ func cacheIsValid(t *testing.T, bts *BlocksByTimestamp) bool {
 }
 
 func TestBlocksByTimestamp_TestCacheIsValid(t *testing.T) {
-	bts := NewBlocksByTimestamp(BTS_MAX_BLOCKS)
+	bts := NewBlocksByTimestamp(BTS_MAX_BLOCKS, false)
 
 	// Empty cache is valid.
 	assert.True(t, cacheIsValid(t, bts))
@@ -61,7 +61,7 @@ func TestBlocksByTimestamp_TestCacheIsValid(t *testing.T) {
 
 func TestBlocksByTimestamp_AddLatest(t *testing.T) {
 	logger := zap.NewNop()
-	bts := NewBlocksByTimestamp(BTS_MAX_BLOCKS)
+	bts := NewBlocksByTimestamp(BTS_MAX_BLOCKS, false)
 
 	bts.AddLatest(logger, 1698621628, 420)
 	bts.AddLatest(logger, 1698621628, 421)
@@ -89,7 +89,7 @@ func TestBlocksByTimestamp_AddLatest(t *testing.T) {
 
 func TestBlocksByTimestamp_AddLatestRollbackEverything(t *testing.T) {
 	logger := zap.NewNop()
-	bts := NewBlocksByTimestamp(BTS_MAX_BLOCKS)
+	bts := NewBlocksByTimestamp(BTS_MAX_BLOCKS, false)
 
 	bts.AddLatest(logger, 1698621628, 420)
 	require.Equal(t, 1, len(bts.cache))
@@ -138,7 +138,7 @@ func TestBlocksByTimestamp_AddLatestRollbackEverything(t *testing.T) {
 
 func TestBlocksByTimestamp_AddLatestShouldTrimTheCache(t *testing.T) {
 	logger := zap.NewNop()
-	bts := NewBlocksByTimestamp(5)
+	bts := NewBlocksByTimestamp(5, false)
 
 	bts.AddLatest(logger, 1698621628, 420)
 	bts.AddLatest(logger, 1698621628, 421)
@@ -161,7 +161,7 @@ func TestBlocksByTimestamp_AddLatestShouldTrimTheCache(t *testing.T) {
 
 func TestBlocksByTimestamp_AddBatch(t *testing.T) {
 	logger := zap.NewNop()
-	bts := NewBlocksByTimestamp(BTS_MAX_BLOCKS)
+	bts := NewBlocksByTimestamp(BTS_MAX_BLOCKS, false)
 
 	// First create a cache with some gaps in it.
 	bts.AddLatest(logger, 1698621628, 420)
@@ -192,7 +192,7 @@ func TestBlocksByTimestamp_AddBatch(t *testing.T) {
 
 func TestBlocksByTimestamp_AddBatchShouldTrim(t *testing.T) {
 	logger := zap.NewNop()
-	bts := NewBlocksByTimestamp(8)
+	bts := NewBlocksByTimestamp(8, false)
 
 	// First create a cache with some gaps in it.
 	bts.AddLatest(logger, 1698621628, 420)
@@ -249,7 +249,7 @@ func TestBlocksByTimestamp_SearchForTimestamp(t *testing.T) {
 
 func TestBlocksByTimestamp_LookUp(t *testing.T) {
 	logger := zap.NewNop()
-	bts := NewBlocksByTimestamp(BTS_MAX_BLOCKS)
+	bts := NewBlocksByTimestamp(BTS_MAX_BLOCKS, false)
 
 	// Empty cache.
 	prev, next, found := bts.LookUp(1698621627)

+ 1 - 2
node/pkg/watchers/evm/watcher.go

@@ -260,7 +260,7 @@ func (w *Watcher) Run(parentCtx context.Context) error {
 	}
 
 	if w.ccqConfig.TimestampCacheSupported {
-		w.ccqTimestampCache = NewBlocksByTimestamp(BTS_MAX_BLOCKS)
+		w.ccqTimestampCache = NewBlocksByTimestamp(BTS_MAX_BLOCKS, w.unsafeDevMode)
 	}
 
 	errC := make(chan error)
@@ -702,7 +702,6 @@ func (w *Watcher) getFinality(ctx context.Context) (bool, bool, error) {
 	finalized := false
 	safe := false
 	if w.unsafeDevMode {
-		// Devnet supports finalized and safe (although they returns the same value as latest).
 		finalized = true
 		safe = true
 	} else if w.chainID == vaa.ChainIDAcala ||

+ 10 - 0
sdk/js-query/ci-config.js

@@ -1,3 +1,13 @@
 process.env.CI = true;
 
+const warn = console.warn;
+console.warn = function (x) {
+  if (
+    x !==
+    "bigint: Failed to load bindings, pure JS will be used (try npm run rebuild?)"
+  ) {
+    warn(x);
+  }
+};
+
 module.exports = {};

+ 29 - 32
sdk/js-query/src/query/ethCall.test.ts

@@ -1,34 +1,26 @@
-import {
-  afterAll,
-  beforeAll,
-  describe,
-  expect,
-  jest,
-  test,
-} from "@jest/globals";
+import { beforeAll, describe, expect, jest, test } from "@jest/globals";
+import axios, { AxiosResponse } from "axios";
 import Web3, { ETH_DATA_FORMAT } from "web3";
-import axios from "axios";
-import { AxiosResponse } from "axios";
 import {
   ChainQueryType,
+  EthCallByTimestampQueryRequest,
+  EthCallByTimestampQueryResponse,
   EthCallData,
   EthCallQueryRequest,
-  EthCallByTimestampQueryRequest,
+  EthCallQueryResponse,
   EthCallWithFinalityQueryRequest,
+  EthCallWithFinalityQueryResponse,
   PerChainQueryRequest,
   QueryRequest,
-  sign,
   QueryResponse,
-  EthCallQueryResponse,
-  EthCallByTimestampQueryResponse,
-  EthCallWithFinalityQueryResponse,
+  sign,
 } from "..";
 
 jest.setTimeout(125000);
 
 const CI = process.env.CI;
 const ENV = "DEVNET";
-const ETH_NODE_URL = CI ? "ws://eth-devnet:8545" : "ws://localhost:8545";
+const ETH_NODE_URL = CI ? "http://eth-devnet:8545" : "http://localhost:8545";
 
 const SERVER_URL = CI ? "http://query-server:" : "http://localhost:";
 const CCQ_SERVER_URL = SERVER_URL + "6069/v1";
@@ -44,10 +36,6 @@ beforeAll(() => {
   web3 = new Web3(ETH_NODE_URL);
 });
 
-afterAll(() => {
-  web3.provider?.disconnect();
-});
-
 function createTestEthCallData(
   to: string,
   name: string,
@@ -162,7 +150,7 @@ describe("eth call", () => {
     );
 
     const ecr = queryResponse.responses[0].response as EthCallQueryResponse;
-    expect(ecr.blockNumber).toEqual(BigInt(blockNumber));
+    expect(ecr.blockNumber.toString()).toEqual(BigInt(blockNumber).toString());
     expect(ecr.blockHash).toEqual(
       (await web3.eth.getBlock(BigInt(blockNumber))).hash
     );
@@ -176,8 +164,7 @@ describe("eth call", () => {
       "0x0000000000000000000000000000000000000000000000000000000000000012"
     );
   });
-  // TODO: This test works in Goerli testnet but not devnet. Try it again after PR #3395 lands.
-  test.skip("get block by hash should work", async () => {
+  test("get block by hash should work", async () => {
     const nameCallData = createTestEthCallData(WETH_ADDRESS, "name", "string");
     const decimalsCallData = createTestEthCallData(
       WETH_ADDRESS,
@@ -461,11 +448,15 @@ describe("eth call", () => {
 
     const ecr = queryResponse.responses[0]
       .response as EthCallByTimestampQueryResponse;
-    expect(ecr.targetBlockNumber).toEqual(BigInt(targetBlockNumber));
+    expect(ecr.targetBlockNumber.toString()).toEqual(
+      BigInt(targetBlockNumber).toString()
+    );
     expect(ecr.targetBlockHash).toEqual(
       (await web3.eth.getBlock(BigInt(targetBlockNumber))).hash
     );
-    expect(ecr.followingBlockNumber).toEqual(BigInt(followingBlockNumber));
+    expect(ecr.followingBlockNumber.toString()).toEqual(
+      BigInt(followingBlockNumber).toString()
+    );
     expect(ecr.followingBlockHash).toEqual(
       (await web3.eth.getBlock(BigInt(followingBlockNumber))).hash
     );
@@ -523,11 +514,15 @@ describe("eth call", () => {
 
     const ecr = queryResponse.responses[0]
       .response as EthCallByTimestampQueryResponse;
-    expect(ecr.targetBlockNumber).toEqual(BigInt(targetBlockNumber));
+    expect(ecr.targetBlockNumber.toString()).toEqual(
+      BigInt(targetBlockNumber).toString()
+    );
     expect(ecr.targetBlockHash).toEqual(
       (await web3.eth.getBlock(BigInt(targetBlockNumber))).hash
     );
-    expect(ecr.followingBlockNumber).toEqual(BigInt(followingBlockNumber));
+    expect(ecr.followingBlockNumber.toString()).toEqual(
+      BigInt(followingBlockNumber).toString()
+    );
     expect(ecr.followingBlockHash).toEqual(
       (await web3.eth.getBlock(BigInt(followingBlockNumber))).hash
     );
@@ -703,9 +698,9 @@ describe("eth call", () => {
       "decimals",
       "uint8"
     );
-    // Jump into the future a bit so the watcher has to wait for finality.
-    const blockNumber =
-      Number(await web3.eth.getBlockNumber(ETH_DATA_FORMAT)) + 10;
+    const blockNumber = Number(
+      (await web3.eth.getBlock("finalized", false, ETH_DATA_FORMAT)).number
+    );
     const ethCall = new EthCallWithFinalityQueryRequest(
       blockNumber.toString(16),
       "finalized",
@@ -740,7 +735,7 @@ describe("eth call", () => {
 
     const ecr = queryResponse.responses[0]
       .response as EthCallWithFinalityQueryResponse;
-    expect(ecr.blockNumber).toEqual(BigInt(blockNumber));
+    expect(ecr.blockNumber.toString()).toEqual(BigInt(blockNumber).toString());
     expect(ecr.blockHash).toEqual(
       (await web3.eth.getBlock(BigInt(blockNumber))).hash
     );
@@ -881,7 +876,9 @@ describe("eth call", () => {
       );
 
       const ecr = queryResponse.responses[0].response as EthCallQueryResponse;
-      expect(ecr.blockNumber).toEqual(BigInt(blockNumber));
+      expect(ecr.blockNumber.toString()).toEqual(
+        BigInt(blockNumber).toString()
+      );
       expect(ecr.blockHash).toEqual(
         (await web3.eth.getBlock(BigInt(blockNumber))).hash
       );

+ 25 - 0
sdk/js/ci-config.js

@@ -1,3 +1,28 @@
 process.env.CI = true;
 
+const info = console.info;
+console.info = function (x) {
+  if (x !== "secp256k1 unavailable, reverting to browser version") {
+    info(x);
+  }
+};
+
+const warn = console.warn;
+console.warn = function (x) {
+  if (
+    x !==
+      "bigint: Failed to load bindings, pure JS will be used (try npm run rebuild?)" &&
+    !(
+      typeof x === "object" &&
+      x
+        .toString()
+        .includes(
+          "RPC Validation Error: The response returned from RPC server does not match the TypeScript definition. This is likely because the SDK version is not compatible with the RPC server."
+        )
+    )
+  ) {
+    warn(x);
+  }
+};
+
 export default {};

+ 1 - 1
sdk/js/jestconfig.json → sdk/js/jest.config.json

@@ -5,5 +5,5 @@
   "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
   "testPathIgnorePatterns": ["__tests__/utils"],
   "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"],
-  "testTimeout": 60000
+  "testTimeout": 300000
 }

+ 4 - 4
sdk/js/package.json

@@ -18,10 +18,10 @@
     "build-lib": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && node scripts/copyEthersTypes.js",
     "build-all": "npm run build-deps && npm run build-lib",
     "docs": "typedoc src/index.ts",
-    "test": "DEV=true NETWORK=DEVNET jest --config jestconfig.json --verbose",
-    "test-ci": "NETWORK=DEVNET NEAR_NO_LOGS=true jest --config jestconfig.json --verbose --setupFiles ./ci-config.js --forceExit",
-    "test-relayer-mainnet": "ENV=mainnet NETWORK=MAINNET npx jest --config jestconfig.json --verbose ./src/relayer/",
-    "test-relayer-testnet": "ENV=testnet NETWORK=TESTNET npx jest --config jestconfig.json --verbose ./src/relayer/",
+    "test": "DEV=true NETWORK=DEVNET jest --verbose",
+    "test-ci": "NETWORK=DEVNET NEAR_NO_LOGS=true jest --verbose --setupFiles ./ci-config.js --forceExit",
+    "test-relayer-mainnet": "ENV=mainnet NETWORK=MAINNET npx jest --verbose ./src/relayer/",
+    "test-relayer-testnet": "ENV=testnet NETWORK=TESTNET npx jest --verbose ./src/relayer/",
     "build": "npm run build-all",
     "format": "echo \"disabled: prettier --write \"src/**/*.ts\"\"",
     "lint": "tslint -p tsconfig.json",

+ 0 - 2
sdk/js/src/algorand/__tests__/unit.ts

@@ -27,8 +27,6 @@ import { PopulateData, TmplSig } from "../TmplSig";
 const CORE_ID = BigInt(1004);
 const TOKEN_BRIDGE_ID = BigInt(1006);
 
-jest.setTimeout(120000);
-
 describe("Unit Tests", () => {
   describe("Algorand unit tests", () => {
     test("Test TmplSig populate()", (done) => {

+ 1 - 3
sdk/js/src/bridge/__tests__/wormhole_ibc_e2e.ts

@@ -16,7 +16,7 @@ import {
   getSignedVAABySequence,
   waitForTerraExecution,
 } from "../../token_bridge/__tests__/utils/helpers";
-import { CHAIN_ID_SEI, CHAIN_ID_TERRA2 } from "../../utils/consts";
+import { CHAIN_ID_SEI } from "../../utils/consts";
 
 const TERRA2_PRIVATE_KEY_4 =
   "bounce success option birth apple portion aunt rural episode solution hockey pencil lend session cause hedgehog slender journey system canvas decorate razor catch empty";
@@ -58,7 +58,6 @@ const terraBroadcastTxAndGetSignedVaa = async (
   if (!txSequence) {
     throw new Error("tx sequence not found");
   }
-  console.log(`${CHAIN_ID_SEI}/${emitter}/${txSequence}`);
   return await getSignedVAABySequence(CHAIN_ID_SEI, txSequence, emitter);
 };
 
@@ -79,6 +78,5 @@ describe("IBC Watcher Integration Tests", () => {
       terraWallet,
       await getEmitterAddressTerra(terraWalletAddress)
     );
-    console.log(postedVaa);
   });
 });

+ 4 - 4
sdk/js/src/nft_bridge/__tests__/aptos-integration.ts

@@ -55,8 +55,6 @@ import {
   getSignedVaaSolana,
 } from "./utils/getSignedVaa";
 
-jest.setTimeout(120000);
-
 const APTOS_NFT_BRIDGE_ADDRESS = CONTRACTS.DEVNET.aptos.nft_bridge;
 const ETH_NFT_BRIDGE_ADDRESS = CONTRACTS.DEVNET.ethereum.nft_bridge;
 const SOLANA_NFT_BRIDGE_ADDRESS = CONTRACTS.DEVNET.solana.nft_bridge;
@@ -69,7 +67,7 @@ let faucet: FaucetClient;
 
 // ethereum setup
 const web3 = new Web3(ETH_NODE_URL);
-const ethProvider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+const ethProvider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
 const ethSigner = new ethers.Wallet(ETH_PRIVATE_KEY8, ethProvider);
 
 // solana setup
@@ -86,7 +84,6 @@ beforeEach(async () => {
 
 afterAll(async () => {
   (web3.currentProvider as any).disconnect();
-  await ethProvider.destroy();
 });
 
 describe("Aptos NFT SDK tests", () => {
@@ -112,6 +109,7 @@ describe("Aptos NFT SDK tests", () => {
       CHAIN_ID_APTOS,
       aptosAccount.address().toUint8Array()
     );
+    await ethProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
 
     // observe tx and get vaa
     const ethTransferVaa = await getSignedVaaEthereum(ethTransferTx);
@@ -313,6 +311,7 @@ describe("Aptos NFT SDK tests", () => {
       tryNativeToUint8Array(aptosAccount.address().toString(), CHAIN_ID_APTOS)
     );
     expect(ethTransferTx.status).toBe(1);
+    await ethProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
 
     // observe tx and get vaa
     const ethTransferVaa = await getSignedVaaEthereum(ethTransferTx);
@@ -455,6 +454,7 @@ describe("Aptos NFT SDK tests", () => {
       CHAIN_ID_APTOS,
       aptosAccount.address().toUint8Array()
     );
+    await ethProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
 
     // observe txs and get vaas
     const ethTransferVaa1 = await getSignedVaaEthereum(ethTransferTx1);

+ 5 - 17
sdk/js/src/nft_bridge/__tests__/integration.ts

@@ -1,11 +1,4 @@
-import {
-  afterEach,
-  beforeEach,
-  describe,
-  expect,
-  jest,
-  test,
-} from "@jest/globals";
+import { beforeEach, describe, expect, jest, test } from "@jest/globals";
 import { getAssociatedTokenAddress } from "@solana/spl-token";
 import {
   Connection,
@@ -16,10 +9,10 @@ import {
 import { BigNumberish, ethers } from "ethers";
 import Web3 from "web3";
 import {
-  ChainId,
   CHAIN_ID_ETH,
   CHAIN_ID_SOLANA,
   CONTRACTS,
+  ChainId,
   nft_bridge,
 } from "../..";
 import { postVaaSolanaWithRetry } from "../../solana";
@@ -34,11 +27,9 @@ import {
 } from "./utils/consts";
 import { getSignedVaaEthereum, getSignedVaaSolana } from "./utils/getSignedVaa";
 
-jest.setTimeout(120000);
-
 // ethereum setup
 const web3 = new Web3(ETH_NODE_URL);
-let provider: ethers.providers.WebSocketProvider;
+let provider: ethers.providers.JsonRpcProvider;
 let signer: ethers.Wallet;
 
 // solana setup
@@ -47,14 +38,10 @@ const keypair = Keypair.fromSecretKey(SOLANA_PRIVATE_KEY);
 const payerAddress = keypair.publicKey.toString();
 
 beforeEach(() => {
-  provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+  provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
   signer = new ethers.Wallet(ETH_PRIVATE_KEY, provider); // corresponds to accounts[1]
 });
 
-afterEach(() => {
-  provider.destroy();
-});
-
 describe("Integration Tests", () => {
   test("Send Solana SPL to Ethereum and back", (done) => {
     (async () => {
@@ -93,6 +80,7 @@ describe("Integration Tests", () => {
           fromAddress.toString(),
           CHAIN_ID_SOLANA
         );
+        await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
         signedVAA = await getSignedVaaEthereum(transaction3);
 
         const { name, symbol } = parseNftTransferVaa(signedVAA);

+ 3 - 1
sdk/js/src/nft_bridge/__tests__/utils/consts.ts

@@ -4,7 +4,9 @@ import { Connection, PublicKey } from "@solana/web3.js";
 const ci = !!process.env.CI;
 
 // see devnet.md
-export const ETH_NODE_URL = ci ? "ws://eth-devnet:8545" : "ws://localhost:8545";
+export const ETH_NODE_URL = ci
+  ? "http://eth-devnet:8545"
+  : "http://localhost:8545";
 export const ETH_PRIVATE_KEY =
   "0x6cbed15c793ce57650b9877cf6fa156fbef513c4e6134f022a85b1ffdd59b2a1"; // account 1
 export const ETH_PRIVATE_KEY8 =

+ 97 - 82
sdk/js/src/relayer/__tests__/wormhole_relayer.ts

@@ -1,34 +1,33 @@
+import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
 import { describe, expect, test } from "@jest/globals";
 import { ContractReceipt, ethers } from "ethers";
 import {
-  getNetwork,
-  isCI,
-  waitForRelay,
-  PRIVATE_KEY,
-  getGuardianRPC,
-  GUARDIAN_KEYS,
-  GUARDIAN_SET_INDEX,
-  GOVERNANCE_EMITTER_ADDRESS,
-  getArbitraryBytes32,
-} from "./utils/utils";
-import { getAddressInfo } from "../consts";
-import { getDefaultProvider } from "../relayer/helpers";
-import {
-  relayer,
-  ethers_contracts,
-  ethers_relayer_contracts,
-  tryNativeToUint8Array,
-  ChainId,
   CHAINS,
   CONTRACTS,
+  ChainId,
   ChainName,
   Network,
+  ethers_relayer_contracts,
+  relayer,
+  tryNativeToUint8Array,
 } from "../../../";
 import { GovernanceEmitter, MockGuardians } from "../../../src/mock";
 import { Implementation__factory } from "../../ethers-contracts";
+import { getAddressInfo } from "../consts";
 import { manualDelivery } from "../relayer";
-import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
+import { getDefaultProvider } from "../relayer/helpers";
 import { packEVMExecutionInfoV1 } from "../structs";
+import {
+  GOVERNANCE_EMITTER_ADDRESS,
+  GUARDIAN_KEYS,
+  GUARDIAN_SET_INDEX,
+  PRIVATE_KEY,
+  getArbitraryBytes32,
+  getGuardianRPC,
+  getNetwork,
+  isCI,
+  waitForRelay,
+} from "./utils/utils";
 
 const network: Network = getNetwork();
 const ci: boolean = isCI();
@@ -42,7 +41,7 @@ const testIfNotDevnet = () => (network != "DEVNET" ? test : test.skip);
 type TestChain = {
   chainId: ChainId;
   name: ChainName;
-  provider: ethers.providers.Provider;
+  provider: ethers.providers.StaticJsonRpcProvider;
   wallet: ethers.Wallet;
   wormholeRelayerAddress: string;
   mockIntegrationAddress: string;
@@ -160,7 +159,7 @@ const testSend = async (
     notEnoughValue ? TOO_LOW_GAS_LIMIT : REASONABLE_GAS_LIMIT,
     optionalParams
   );
-  console.log(`Quoted gas delivery fee: ${value}`);
+  !ci && console.log(`Quoted gas delivery fee: ${value}`);
   const tx = await source.mockIntegration.sendMessage(
     payload,
     sendToSourceChain ? source.chainId : target.chainId,
@@ -168,9 +167,9 @@ const testSend = async (
     0,
     { value, gasLimit: REASONABLE_GAS_LIMIT }
   );
-  console.log(`Sent delivery request! Transaction hash ${tx.hash}`);
+  !ci && console.log(`Sent delivery request! Transaction hash ${tx.hash}`);
   await tx.wait();
-  console.log("Message confirmed!");
+  !ci && console.log("Message confirmed!");
 
   return tx.wait();
 };
@@ -178,20 +177,20 @@ const testSend = async (
 describe("Wormhole Relayer Tests", () => {
   test("Executes a Delivery Success", async () => {
     const arbitraryPayload = getArbitraryBytes32();
-    console.log(`Sent message: ${arbitraryPayload}`);
+    !ci && console.log(`Sent message: ${arbitraryPayload}`);
 
     const rx = await testSend(arbitraryPayload);
 
     await waitForRelay();
 
-    console.log("Checking if message was relayed");
+    !ci && console.log("Checking if message was relayed");
     const message = await target.mockIntegration.getMessage();
     expect(message).toBe(arbitraryPayload);
   });
 
   test("Executes a Delivery Success With Additional VAAs", async () => {
     const arbitraryPayload = getArbitraryBytes32();
-    console.log(`Sent message: ${arbitraryPayload}`);
+    !ci && console.log(`Sent message: ${arbitraryPayload}`);
 
     const wormhole = Implementation__factory.connect(
       CONTRACTS[network][sourceChain].core || "",
@@ -207,7 +206,7 @@ describe("Wormhole Relayer Tests", () => {
       REASONABLE_GAS_LIMIT * 2,
       optionalParams
     );
-    console.log(`Quoted gas delivery fee: ${value}`);
+    !ci && console.log(`Quoted gas delivery fee: ${value}`);
 
     const tx = await source.mockIntegration.sendMessageWithAdditionalVaas(
       [],
@@ -224,13 +223,13 @@ describe("Wormhole Relayer Tests", () => {
       { value }
     );
 
-    console.log(`Sent tx hash: ${tx.hash}`);
+    !ci && console.log(`Sent tx hash: ${tx.hash}`);
 
     const rx = await tx.wait();
 
     await waitForRelay();
 
-    console.log("Checking if message was relayed");
+    !ci && console.log("Checking if message was relayed");
     const message = (await target.mockIntegration.getDeliveryData())
       .additionalVaas[0];
     const parsedMessage = await wormhole.parseVM(message);
@@ -241,7 +240,7 @@ describe("Wormhole Relayer Tests", () => {
     "Executes a Delivery Success with manual delivery",
     async () => {
       const arbitraryPayload = getArbitraryBytes32();
-      console.log(`Sent message: ${arbitraryPayload}`);
+      !ci && console.log(`Sent message: ${arbitraryPayload}`);
 
       const deliverySeq = await Implementation__factory.connect(
         CONTRACTS[network][sourceChain].core || "",
@@ -286,7 +285,10 @@ describe("Wormhole Relayer Tests", () => {
         }
       );
 
-      console.log(`Price: ${priceInfo.quote} of ${priceInfo.targetChain} wei`);
+      !ci &&
+        console.log(
+          `Price: ${priceInfo.quote} of ${priceInfo.targetChain} wei`
+        );
 
       const deliveryRx = await manualDelivery(
         sourceChain,
@@ -310,9 +312,9 @@ describe("Wormhole Relayer Tests", () => {
         },
         target.wallet
       );
-      console.log("Manual delivery tx hash", deliveryRx.txHash);
+      !ci && console.log("Manual delivery tx hash", deliveryRx.txHash);
 
-      console.log("Checking if message was relayed");
+      !ci && console.log("Checking if message was relayed");
       const message = await target.mockIntegration.getMessage();
       expect(message).toBe(arbitraryPayload);
     }
@@ -330,14 +332,14 @@ describe("Wormhole Relayer Tests", () => {
 
   test("Executes a delivery with a Cross Chain Refund", async () => {
     const arbitraryPayload = getArbitraryBytes32();
-    console.log(`Sent message: ${arbitraryPayload}`);
+    !ci && console.log(`Sent message: ${arbitraryPayload}`);
     const value = await relayer.getPrice(
       sourceChain,
       targetChain,
       REASONABLE_GAS_LIMIT,
       optionalParams
     );
-    console.log(`Quoted gas delivery fee: ${value}`);
+    !ci && console.log(`Quoted gas delivery fee: ${value}`);
     const startingBalance = await source.wallet.getBalance();
 
     const tx = await relayer.sendToEvm(
@@ -350,11 +352,13 @@ describe("Wormhole Relayer Tests", () => {
       { value, gasLimit: REASONABLE_GAS_LIMIT },
       optionalParams
     );
-    console.log("Sent delivery request!");
+    !ci && console.log("Sent delivery request!");
     await tx.wait();
-    console.log("Message confirmed!");
+    !ci && console.log("Message confirmed!");
     const endingBalance = await source.wallet.getBalance();
 
+    await source.provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
+
     await waitForRelay();
 
     const info = (await relayer.getWormholeRelayerInfo(sourceChain, tx.hash, {
@@ -362,30 +366,34 @@ describe("Wormhole Relayer Tests", () => {
       ...optionalParams,
     })) as relayer.DeliveryInfo;
 
+    await target.provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
+
     await waitForRelay();
 
     const newEndingBalance = await source.wallet.getBalance();
 
-    console.log(`Quoted gas delivery fee: ${value}`);
-    console.log(
-      `Cost (including gas) ${startingBalance.sub(endingBalance).toString()}`
-    );
+    !ci && console.log(`Quoted gas delivery fee: ${value}`);
+    !ci &&
+      console.log(
+        `Cost (including gas) ${startingBalance.sub(endingBalance).toString()}`
+      );
     const refund = newEndingBalance.sub(endingBalance);
-    console.log(`Refund: ${refund.toString()}`);
-    console.log(
-      `As a percentage of original value: ${newEndingBalance
-        .sub(endingBalance)
-        .mul(100)
-        .div(value)
-        .toString()}%`
-    );
-    console.log("Confirming refund is nonzero");
+    !ci && console.log(`Refund: ${refund.toString()}`);
+    !ci &&
+      console.log(
+        `As a percentage of original value: ${newEndingBalance
+          .sub(endingBalance)
+          .mul(100)
+          .div(value)
+          .toString()}%`
+      );
+    !ci && console.log("Confirming refund is nonzero");
     expect(refund.gt(0)).toBe(true);
   });
 
   test("Executes a Receiver Failure", async () => {
     const arbitraryPayload = getArbitraryBytes32();
-    console.log(`Sent message: ${arbitraryPayload}`);
+    !ci && console.log(`Sent message: ${arbitraryPayload}`);
 
     const rx = await testSend(arbitraryPayload, false, true);
 
@@ -397,7 +405,7 @@ describe("Wormhole Relayer Tests", () => {
 
   test("Executes a receiver failure and then redelivery through SDK", async () => {
     const arbitraryPayload = getArbitraryBytes32();
-    console.log(`Sent message: ${arbitraryPayload}`);
+    !ci && console.log(`Sent message: ${arbitraryPayload}`);
 
     const rx = await testSend(arbitraryPayload, false, true);
 
@@ -419,7 +427,7 @@ describe("Wormhole Relayer Tests", () => {
       { wormholeRelayerAddresses, ...optionalParams }
     )) as relayer.DeliveryInfo;
 
-    console.log("Redelivering message");
+    !ci && console.log("Redelivering message");
     const redeliveryReceipt = await relayer.resend(
       source.wallet,
       sourceChain,
@@ -444,13 +452,13 @@ describe("Wormhole Relayer Tests", () => {
       { wormholeRelayerAddress: source.wormholeRelayerAddress }
     );
 
-    console.log("redelivery tx:", redeliveryReceipt.hash);
+    !ci && console.log("redelivery tx:", redeliveryReceipt.hash);
 
     await redeliveryReceipt.wait();
 
     await waitForRelay();
 
-    console.log("Checking if message was relayed after redelivery");
+    !ci && console.log("Checking if message was relayed after redelivery");
     const message2 = await target.mockIntegration.getMessage();
     expect(message2).toBe(arbitraryPayload);
 
@@ -464,9 +472,10 @@ describe("Wormhole Relayer Tests", () => {
 
     const currentAddress =
       await source.wormholeRelayer.getRegisteredWormholeRelayerContract(chain);
-    console.log(
-      `For Chain ${source.chainId}, registered chain ${chain} address: ${currentAddress}`
-    );
+    !ci &&
+      console.log(
+        `For Chain ${source.chainId}, registered chain ${chain} address: ${currentAddress}`
+      );
 
     const expectedNewRegisteredAddress =
       "0x0000000000000000000000001234567890123456789012345678901234567892";
@@ -501,9 +510,10 @@ describe("Wormhole Relayer Tests", () => {
     async () => {
       const currentAddress =
         await source.wormholeRelayer.getDefaultDeliveryProvider();
-      console.log(
-        `For Chain ${source.chainId}, default relay provider: ${currentAddress}`
-      );
+      !ci &&
+        console.log(
+          `For Chain ${source.chainId}, default relay provider: ${currentAddress}`
+        );
 
       const expectedNewDefaultDeliveryProvider =
         "0x1234567890123456789012345678901234567892";
@@ -567,9 +577,10 @@ describe("Wormhole Relayer Tests", () => {
         IMPLEMENTATION_STORAGE_SLOT
       );
 
-    console.log(
-      `Current Implementation address: ${await getImplementationAddress()}`
-    );
+    !ci &&
+      console.log(
+        `Current Implementation address: ${await getImplementationAddress()}`
+      );
 
     const wormholeAddress = CONTRACTS[network][sourceChain].core || "";
 
@@ -579,10 +590,11 @@ describe("Wormhole Relayer Tests", () => {
         .then((x) => x.deployed())
     ).address;
 
-    console.log(`Deployed!`);
-    console.log(
-      `New core relayer implementation: ${newWormholeRelayerImplementationAddress}`
-    );
+    !ci && console.log(`Deployed!`);
+    !ci &&
+      console.log(
+        `New core relayer implementation: ${newWormholeRelayerImplementationAddress}`
+      );
 
     const timestamp = (await source.wallet.provider.getBlock("latest"))
       .timestamp;
@@ -598,6 +610,7 @@ describe("Wormhole Relayer Tests", () => {
     );
 
     let tx = await source.wormholeRelayer.submitContractUpgrade(firstSignedVaa);
+    await tx.wait();
 
     expect(
       ethers.utils.getAddress((await getImplementationAddress()).substring(26))
@@ -613,7 +626,7 @@ describe("Wormhole Relayer Tests", () => {
     const info = await relayer.getWormholeRelayerInfo(mySourceChain, txHash, {
       environment,
     });
-    console.log(info.stringified);
+    !ci && console.log(info.stringified);
   });
 
   testIfNotDevnet()("Tests custom manual delivery", async () => {
@@ -626,7 +639,7 @@ describe("Wormhole Relayer Tests", () => {
     const info = await relayer.getWormholeRelayerInfo(mySourceChain, txHash, {
       environment,
     });
-    console.log(info.stringified);
+    !ci && console.log(info.stringified);
 
     const priceInfo = await manualDelivery(
       mySourceChain,
@@ -634,7 +647,7 @@ describe("Wormhole Relayer Tests", () => {
       { environment },
       true
     );
-    console.log(`Price info: ${JSON.stringify(priceInfo)}`);
+    !ci && console.log(`Price info: ${JSON.stringify(priceInfo)}`);
 
     const signer = new ethers.Wallet(
       PRIVATE_KEY,
@@ -643,17 +656,19 @@ describe("Wormhole Relayer Tests", () => {
         : getDefaultProvider(environment, priceInfo.targetChain)
     );
 
-    console.log(
-      `Price: ${ethers.utils.formatEther(priceInfo.quote)} of ${
-        priceInfo.targetChain
-      } currency`
-    );
+    !ci &&
+      console.log(
+        `Price: ${ethers.utils.formatEther(priceInfo.quote)} of ${
+          priceInfo.targetChain
+        } currency`
+      );
     const balance = await signer.getBalance();
-    console.log(
-      `My balance: ${ethers.utils.formatEther(balance)} of ${
-        priceInfo.targetChain
-      } currency`
-    );
+    !ci &&
+      console.log(
+        `My balance: ${ethers.utils.formatEther(balance)} of ${
+          priceInfo.targetChain
+        } currency`
+      );
 
     const deliveryRx = await manualDelivery(
       mySourceChain,
@@ -663,7 +678,7 @@ describe("Wormhole Relayer Tests", () => {
       undefined,
       signer
     );
-    console.log("Manual delivery tx hash", deliveryRx.txHash);
+    !ci && console.log("Manual delivery tx hash", deliveryRx.txHash);
   });
 });
 

+ 17 - 17
sdk/js/src/token_bridge/__tests__/algorand-integration.ts

@@ -3,20 +3,21 @@ import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport"
 import { describe, expect, jest, test } from "@jest/globals";
 import algosdk, {
   Account,
+  OnApplicationComplete,
   decodeAddress,
   getApplicationAddress,
   makeApplicationCallTxnFromObject,
-  OnApplicationComplete,
   waitForConfirmation,
 } from "algosdk";
 import { BigNumber, ethers, utils } from "ethers";
 import {
-  approveEth,
-  attestFromAlgorand,
-  attestFromEth,
   CHAIN_ID_ALGORAND,
   CHAIN_ID_ETH,
   CONTRACTS,
+  WormholeWrappedInfo,
+  approveEth,
+  attestFromAlgorand,
+  attestFromEth,
   createWrappedOnAlgorand,
   createWrappedOnEth,
   getEmitterAddressAlgorand,
@@ -36,9 +37,7 @@ import {
   transferFromEth,
   uint8ArrayToHex,
   updateWrappedOnEth,
-  WormholeWrappedInfo,
 } from "../..";
-import { TokenImplementation__factory } from "../../ethers-contracts";
 import { _parseVAAAlgorand } from "../../algorand";
 import {
   createAsset,
@@ -49,6 +48,7 @@ import {
   getTempAccounts,
   signSendAndConfirmAlgorand,
 } from "../../algorand/__tests__/testHelpers";
+import { TokenImplementation__factory } from "../../ethers-contracts";
 import getSignedVAAWithRetry from "../../rpc/getSignedVAAWithRetry";
 import { safeBigIntToNumber } from "../../utils/bigint";
 import {
@@ -61,8 +61,6 @@ import {
 const CORE_ID = BigInt(1004);
 const TOKEN_BRIDGE_ID = BigInt(1006);
 
-jest.setTimeout(120000);
-
 describe("Algorand tests", () => {
   test("Algorand transfer native ALGO to Eth and back again", (done) => {
     (async () => {
@@ -115,7 +113,7 @@ describe("Algorand tests", () => {
           { transport: NodeHttpTransport() }
         );
         const pvaa = _parseVAAAlgorand(vaaBytes);
-        const provider = new ethers.providers.WebSocketProvider(
+        const provider = new ethers.providers.JsonRpcProvider(
           ETH_NODE_URL
         ) as any;
         const signer = new ethers.Wallet(ETH_PRIVATE_KEY7, provider);
@@ -262,6 +260,7 @@ describe("Algorand tests", () => {
         const emitterAddress = getEmitterAddressEth(
           CONTRACTS.DEVNET.ethereum.token_bridge
         );
+        await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
 
         // poll until the guardian(s) witness and sign the vaa
         const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
@@ -297,8 +296,6 @@ describe("Algorand tests", () => {
         if (!secondFinalAlgoBal) {
           throw new Error("secondFinalAlgoBal is undefined");
         }
-
-        provider.destroy();
       } catch (e) {
         console.error("Algorand ALGO transfer error:", e);
         done("Algorand ALGO transfer error");
@@ -358,7 +355,7 @@ describe("Algorand tests", () => {
           attestSn,
           { transport: NodeHttpTransport() }
         );
-        const provider = new ethers.providers.WebSocketProvider(
+        const provider = new ethers.providers.JsonRpcProvider(
           ETH_NODE_URL
         ) as any;
         const signer = new ethers.Wallet(ETH_PRIVATE_KEY7, provider);
@@ -501,6 +498,7 @@ describe("Algorand tests", () => {
         const emitterAddress = getEmitterAddressEth(
           CONTRACTS.DEVNET.ethereum.token_bridge
         );
+        await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
 
         // poll until the guardian(s) witness and sign the vaa
         const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
@@ -537,7 +535,6 @@ describe("Algorand tests", () => {
           throw new Error("secondFinalAlgoBal is undefined");
         }
         expect(secondFinalAlgoBal - finalAlgoBal).toBe(parseInt(Amount) * 100);
-        provider.destroy();
       } catch (e) {
         console.error("Algorand chuckNorium transfer error:", e);
         done("Algorand chuckNorium transfer error");
@@ -559,7 +556,7 @@ describe("Algorand tests", () => {
         const algoWallet: Account = tempAccts[0];
         const Amount = "10";
         // create a signer for Eth
-        const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+        const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
         const signer = new ethers.Wallet(ETH_PRIVATE_KEY7, provider);
         // attest the test token
         const attestReceipt = await attestFromEth(
@@ -575,6 +572,7 @@ describe("Algorand tests", () => {
         const emitterAddress = getEmitterAddressEth(
           CONTRACTS.DEVNET.ethereum.token_bridge
         );
+        await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
         // poll until the guardian(s) witness and sign the vaa
         const { vaaBytes: attestSignedVaa } = await getSignedVAAWithRetry(
           WORMHOLE_RPC_HOSTS,
@@ -651,6 +649,7 @@ describe("Algorand tests", () => {
           receipt,
           CONTRACTS.DEVNET.ethereum.core
         );
+        await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
         // poll until the guardian(s) witness and sign the vaa
         const { vaaBytes: transferSignedVaa } = await getSignedVAAWithRetry(
           WORMHOLE_RPC_HOSTS,
@@ -776,7 +775,6 @@ describe("Algorand tests", () => {
         );
         expect(info.chainId).toBe(CHAIN_ID_ETH);
         expect(info.isWrapped).toBe(true);
-        provider.destroy();
       } catch (e) {
         console.error("Eth <=> Algorand error:", e);
         done("Eth <=> Algorand error");
@@ -809,7 +807,7 @@ describe("Algorand tests", () => {
         // ETH setup to transfer LUNA to Algorand
 
         // create a signer for Eth
-        const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+        const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
         const signer = new ethers.Wallet(ETH_PRIVATE_KEY7, provider);
         // attest the test token
         const receipt = await attestFromEth(
@@ -825,6 +823,7 @@ describe("Algorand tests", () => {
         const emitterAddress = getEmitterAddressEth(
           CONTRACTS.DEVNET.ethereum.token_bridge
         );
+        await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
         // poll until the guardian(s) witness and sign the vaa
         const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
           WORMHOLE_RPC_HOSTS,
@@ -880,6 +879,7 @@ describe("Algorand tests", () => {
         const ethEmitterAddress = getEmitterAddressEth(
           CONTRACTS.DEVNET.ethereum.token_bridge
         );
+        await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
         // poll until the guardian(s) witness and sign the vaa
         const { vaaBytes: firstHalfVaa } = await getSignedVAAWithRetry(
           WORMHOLE_RPC_HOSTS,
@@ -925,6 +925,7 @@ describe("Algorand tests", () => {
           secondHalfReceipt,
           CONTRACTS.DEVNET.ethereum.core
         );
+        await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
         // poll until the guardian(s) witness and sign the vaa
         const { vaaBytes: secondHalfVaa } = await getSignedVAAWithRetry(
           WORMHOLE_RPC_HOSTS,
@@ -952,7 +953,6 @@ describe("Algorand tests", () => {
             secondHalfVaa
           )
         ).toBe(true);
-        provider.destroy();
       } catch (e) {
         console.error("new test error:", e);
         done("new test error");

+ 8 - 17
sdk/js/src/token_bridge/__tests__/aptos-integration.ts

@@ -10,13 +10,13 @@ import {
 import { ethers } from "ethers";
 import { parseUnits } from "ethers/lib/utils";
 import {
-  approveEth,
   APTOS_TOKEN_BRIDGE_EMITTER_ADDRESS,
-  attestFromAptos,
-  attestFromEth,
   CHAIN_ID_APTOS,
   CHAIN_ID_ETH,
   CONTRACTS,
+  approveEth,
+  attestFromAptos,
+  attestFromEth,
   createWrappedOnAptos,
   createWrappedOnEth,
   createWrappedTypeOnAptos,
@@ -56,8 +56,6 @@ import {
   WORMHOLE_RPC_HOSTS,
 } from "./utils/consts";
 
-jest.setTimeout(120000);
-
 describe("Aptos SDK tests", () => {
   test("Transfer native token from Aptos to Ethereum", async () => {
     const APTOS_TOKEN_BRIDGE = CONTRACTS.DEVNET.aptos.token_bridge;
@@ -99,7 +97,7 @@ describe("Aptos SDK tests", () => {
     expect(attestVAA).toBeTruthy();
 
     // setup ethereum
-    const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+    const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
     const recipient = new ethers.Wallet(ETH_PRIVATE_KEY6, provider);
     const recipientAddress = await recipient.getAddress();
     const ethTokenBridge = CONTRACTS.DEVNET.ethereum.token_bridge;
@@ -196,13 +194,10 @@ describe("Aptos SDK tests", () => {
     expect(
       balanceAfterTransferEth.sub(balanceBeforeTransferEth).toNumber()
     ).toEqual(10_000_000);
-
-    // clean up
-    provider.destroy();
   });
   test("Transfer native ERC-20 from Ethereum to Aptos", async () => {
     // setup ethereum
-    const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+    const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
     const sender = new ethers.Wallet(ETH_PRIVATE_KEY6, provider);
     const ethTokenBridge = CONTRACTS.DEVNET.ethereum.token_bridge;
     const ethCoreBridge = CONTRACTS.DEVNET.ethereum.core;
@@ -218,6 +213,7 @@ describe("Aptos SDK tests", () => {
     let sequence = parseSequenceFromLogEth(attestReceipt, ethCoreBridge);
     expect(sequence).toBeTruthy();
 
+    await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
     const { vaaBytes: attestVAA } = await getSignedVAAWithRetry(
       WORMHOLE_RPC_HOSTS,
       CHAIN_ID_ETH,
@@ -322,6 +318,7 @@ describe("Aptos SDK tests", () => {
     sequence = parseSequenceFromLogEth(transferReceipt, ethCoreBridge);
     expect(sequence).toBeTruthy();
 
+    await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
     const { vaaBytes: transferVAA } = await getSignedVAAWithRetry(
       WORMHOLE_RPC_HOSTS,
       CHAIN_ID_ETH,
@@ -367,9 +364,6 @@ describe("Aptos SDK tests", () => {
     expect(
       balanceBeforeTransferEth.sub(balanceAfterTransferEth).toString()
     ).toEqual(amount.toString());
-
-    // clean up
-    provider.destroy();
   });
   test("Transfer native token with payload from Aptos to Ethereum", async () => {
     const APTOS_TOKEN_BRIDGE = CONTRACTS.DEVNET.aptos.token_bridge;
@@ -411,7 +405,7 @@ describe("Aptos SDK tests", () => {
     expect(attestVAA).toBeTruthy();
 
     // setup ethereum
-    const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+    const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
     const recipient = new ethers.Wallet(ETH_PRIVATE_KEY6, provider);
     const recipientAddress = await recipient.getAddress();
     const ethTokenBridge = CONTRACTS.DEVNET.ethereum.token_bridge;
@@ -513,9 +507,6 @@ describe("Aptos SDK tests", () => {
     expect(
       balanceAfterTransferEth.sub(balanceBeforeTransferEth).toNumber()
     ).toEqual(10_000_000);
-
-    // clean up
-    provider.destroy();
   });
 });
 

+ 12 - 12
sdk/js/src/token_bridge/__tests__/eth-integration.ts

@@ -2,10 +2,9 @@ import { formatUnits, parseUnits } from "@ethersproject/units";
 import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
 import { describe, expect, jest, test } from "@jest/globals";
 import {
-  ASSOCIATED_TOKEN_PROGRAM_ID,
+  TOKEN_PROGRAM_ID,
   createAssociatedTokenAccountInstruction,
   getAssociatedTokenAddress,
-  TOKEN_PROGRAM_ID,
 } from "@solana/spl-token";
 import {
   Connection,
@@ -16,11 +15,11 @@ import {
 } from "@solana/web3.js";
 import { ethers } from "ethers";
 import {
-  approveEth,
-  attestFromEth,
   CHAIN_ID_ETH,
   CHAIN_ID_SOLANA,
   CONTRACTS,
+  approveEth,
+  attestFromEth,
   createWrappedOnSolana,
   getEmitterAddressEth,
   getForeignAssetSolana,
@@ -43,8 +42,6 @@ import {
   WORMHOLE_RPC_HOSTS,
 } from "./utils/consts";
 
-jest.setTimeout(120000);
-
 async function transferFromEthToSolana(): Promise<string> {
   // create a keypair for Solana
   const connection = new Connection(SOLANA_HOST, "confirmed");
@@ -82,7 +79,7 @@ async function transferFromEthToSolana(): Promise<string> {
     await connection.confirmTransaction(txid);
   }
   // create a signer for Eth
-  const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+  const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
   const signer = new ethers.Wallet(ETH_PRIVATE_KEY, provider);
   const amount = parseUnits("1", 18);
   // approve the bridge to spend tokens
@@ -106,7 +103,6 @@ async function transferFromEthToSolana(): Promise<string> {
     receipt,
     CONTRACTS.DEVNET.ethereum.core
   );
-  provider.destroy();
   return sequence;
 }
 
@@ -115,7 +111,7 @@ describe("Ethereum to Solana and Back", () => {
     (async () => {
       try {
         // create a signer for Eth
-        const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+        const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
         const signer = new ethers.Wallet(ETH_PRIVATE_KEY, provider);
         // attest the test token
         const receipt = await attestFromEth(
@@ -131,6 +127,7 @@ describe("Ethereum to Solana and Back", () => {
         const emitterAddress = getEmitterAddressEth(
           CONTRACTS.DEVNET.ethereum.token_bridge
         );
+        await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
         // poll until the guardian(s) witness and sign the vaa
         const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
           WORMHOLE_RPC_HOSTS,
@@ -174,7 +171,6 @@ describe("Ethereum to Solana and Back", () => {
         } catch (e) {
           // this could fail because the token is already attested (in an unclean env)
         }
-        provider.destroy();
         done();
       } catch (e) {
         console.error(e);
@@ -238,7 +234,7 @@ describe("Ethereum to Solana and Back", () => {
           await connection.confirmTransaction(txid);
         }
         // create a signer for Eth
-        const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+        const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
         const signer = new ethers.Wallet(ETH_PRIVATE_KEY, provider);
         const amount = parseUnits("1", DECIMALS);
 
@@ -294,6 +290,7 @@ describe("Ethereum to Solana and Back", () => {
         const emitterAddress = getEmitterAddressEth(
           CONTRACTS.DEVNET.ethereum.token_bridge
         );
+        await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
         // poll until the guardian(s) witness and sign the vaa
         const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
           WORMHOLE_RPC_HOSTS,
@@ -373,7 +370,6 @@ describe("Ethereum to Solana and Back", () => {
           }
         }
         expect(finalSolanaBalance - initialSolanaBalance === 1).toBe(true);
-        provider.destroy();
         done();
       } catch (e) {
         console.error(e);
@@ -393,6 +389,8 @@ describe("Ethereum to Solana and Back", () => {
           const emitterAddress = getEmitterAddressEth(
             CONTRACTS.DEVNET.ethereum.token_bridge
           );
+          const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
+          await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
           // poll until the guardian(s) witness and sign the vaa
           const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
             WORMHOLE_RPC_HOSTS,
@@ -466,6 +464,8 @@ describe("Ethereum to Solana and Back", () => {
           const emitterAddress = getEmitterAddressEth(
             CONTRACTS.DEVNET.ethereum.token_bridge
           );
+          const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
+          await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
           // poll until the guardian(s) witness and sign the vaa
           const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
             WORMHOLE_RPC_HOSTS,

+ 11 - 15
sdk/js/src/token_bridge/__tests__/near-integration.ts

@@ -1,6 +1,13 @@
-import { beforeAll, afterAll, expect, jest, test } from "@jest/globals";
+import { beforeAll, expect, jest, test } from "@jest/globals";
 import { ethers } from "ethers";
 import { parseUnits } from "ethers/lib/utils";
+import { Account, KeyPair, Near, connect, keyStores } from "near-api-js";
+import {
+  FinalExecutionOutcome,
+  Provider,
+  getTransactionLastResult,
+} from "near-api-js/lib/providers";
+import { parseNearAmount } from "near-api-js/lib/utils/format";
 import {
   createWrappedOnEth,
   createWrappedOnNear,
@@ -28,15 +35,6 @@ import {
   TEST_ERC20,
 } from "./utils/consts";
 import { getSignedVAABySequence } from "./utils/helpers";
-import { Account, connect, KeyPair, keyStores, Near } from "near-api-js";
-import {
-  FinalExecutionOutcome,
-  getTransactionLastResult,
-  Provider,
-} from "near-api-js/lib/providers";
-import { parseNearAmount } from "near-api-js/lib/utils/format";
-
-jest.setTimeout(120000);
 
 let near: Near;
 let nearProvider: Provider;
@@ -46,7 +44,7 @@ const accountId = "devnet.test.near";
 const PRIVATE_KEY =
   "ed25519:nCW2EsTn91b7ettRqQX6ti8ZBNwo7tbMsenBu9nmSVG9aDhNB7hgw7S9w5M9CZu1bF23FbvhKZPfDmh2Gbs45Fs";
 
-const ethProvider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+const ethProvider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
 const signer = new ethers.Wallet(ETH_PRIVATE_KEY5, ethProvider);
 const ethEmitterAddress = getEmitterAddressEth(
   CONTRACTS.DEVNET.ethereum.token_bridge
@@ -72,10 +70,6 @@ beforeAll(async () => {
   ethWalletAddress = await signer.getAddress();
 });
 
-afterAll(async () => {
-  ethProvider.destroy();
-});
-
 const nearParseLogAndGetSignedVaa = async (outcome: FinalExecutionOutcome) => {
   const sequence = parseSequenceFromLogNear(outcome);
   if (sequence === null) {
@@ -155,6 +149,7 @@ test("Attest and transfer token from Ethereum to Near", async () => {
     signer,
     TEST_ERC20
   );
+  await ethProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
   const attestSignedVaa = await ethParseLogAndGetSignedVaa(attestReceipt);
   const createWrappedMsgs = await createWrappedOnNear(
     nearProvider,
@@ -193,6 +188,7 @@ test("Attest and transfer token from Ethereum to Near", async () => {
     "near",
     hexToUint8Array(accountHash)
   );
+  await ethProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
   const transferSignedVaa = await ethParseLogAndGetSignedVaa(transferReceipt);
   const redeemMsgs = await redeemOnNear(
     nearProvider,

+ 8 - 16
sdk/js/src/token_bridge/__tests__/solana-integration.ts

@@ -2,10 +2,9 @@ import { formatUnits, parseUnits } from "@ethersproject/units";
 import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
 import { describe, expect, jest, test } from "@jest/globals";
 import {
-  ASSOCIATED_TOKEN_PROGRAM_ID,
-  getAssociatedTokenAddress,
   NATIVE_MINT,
   TOKEN_PROGRAM_ID,
+  getAssociatedTokenAddress,
 } from "@solana/spl-token";
 import {
   Connection,
@@ -15,10 +14,11 @@ import {
 } from "@solana/web3.js";
 import { ethers } from "ethers";
 import {
-  attestFromSolana,
   CHAIN_ID_ETH,
   CHAIN_ID_SOLANA,
   CONTRACTS,
+  WSOL_ADDRESS,
+  attestFromSolana,
   createWrappedOnEth,
   getEmitterAddressSolana,
   getForeignAssetEth,
@@ -30,7 +30,6 @@ import {
   transferNativeSol,
   tryNativeToHexString,
   tryNativeToUint8Array,
-  WSOL_ADDRESS,
 } from "../..";
 import { TokenImplementation__factory } from "../../ethers-contracts";
 import getSignedVAAWithRetry from "../../rpc/getSignedVAAWithRetry";
@@ -43,8 +42,6 @@ import {
   WORMHOLE_RPC_HOSTS,
 } from "./utils/consts";
 
-jest.setTimeout(120000);
-
 describe("Solana to Ethereum", () => {
   test("Attest Solana SPL to Ethereum", (done) => {
     (async () => {
@@ -89,7 +86,7 @@ describe("Solana to Ethereum", () => {
           }
         );
         // create a signer for Eth
-        const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+        const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
         const signer = new ethers.Wallet(ETH_PRIVATE_KEY3, provider);
         try {
           await createWrappedOnEth(
@@ -100,7 +97,6 @@ describe("Solana to Ethereum", () => {
         } catch (e) {
           // this could fail because the token is already attested (in an unclean env)
         }
-        provider.destroy();
         done();
       } catch (e) {
         console.error(e);
@@ -111,7 +107,7 @@ describe("Solana to Ethereum", () => {
     })();
   });
   test("Solana SPL is attested on Ethereum", async () => {
-    const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+    const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
     const address = getForeignAssetEth(
       CONTRACTS.DEVNET.ethereum.token_bridge,
       provider,
@@ -120,13 +116,12 @@ describe("Solana to Ethereum", () => {
     );
     expect(address).toBeTruthy();
     expect(address).not.toBe(ethers.constants.AddressZero);
-    provider.destroy();
   });
   test("Send Solana SPL to Ethereum", (done) => {
     (async () => {
       try {
         // create a signer for Eth
-        const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+        const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
         const signer = new ethers.Wallet(ETH_PRIVATE_KEY3, provider);
         const targetAddress = await signer.getAddress();
         // create a keypair for Solana
@@ -267,7 +262,6 @@ describe("Solana to Ethereum", () => {
             parseInt(initialBalOnEthFormatted) ===
             1
         ).toBe(true);
-        provider.destroy();
         done();
       } catch (e) {
         console.error(e);
@@ -318,7 +312,7 @@ describe("Solana to Ethereum", () => {
           }
         );
         // create a signer for Eth
-        const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+        const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
         const signer = new ethers.Wallet(ETH_PRIVATE_KEY3, provider);
         try {
           await createWrappedOnEth(
@@ -329,7 +323,6 @@ describe("Solana to Ethereum", () => {
         } catch (e) {
           // this could fail because the token is already attested (in an unclean env)
         }
-        provider.destroy();
         done();
       } catch (e) {
         console.error(e);
@@ -343,7 +336,7 @@ describe("Solana to Ethereum", () => {
     (async () => {
       try {
         // create a signer for Eth
-        const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+        const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
         const signer = new ethers.Wallet(ETH_PRIVATE_KEY3, provider);
         const targetAddress = await signer.getAddress();
         // create a keypair for Solana
@@ -443,7 +436,6 @@ describe("Solana to Ethereum", () => {
             parseInt(initialBalOnEthFormatted) ===
             1
         ).toBe(true);
-        provider.destroy();
         done();
       } catch (e) {
         console.error(e);

+ 4 - 22
sdk/js/src/token_bridge/__tests__/sui-integration.ts

@@ -1,12 +1,5 @@
 import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
-import {
-  afterAll,
-  beforeAll,
-  describe,
-  expect,
-  jest,
-  test,
-} from "@jest/globals";
+import { beforeAll, describe, expect, jest, test } from "@jest/globals";
 import {
   Connection,
   Ed25519Keypair,
@@ -35,9 +28,7 @@ import {
   getSignedVAAWithRetry,
   parseAttestMetaVaa,
   parseSequenceFromLogEth,
-  parseTokenTransferPayload,
   parseTokenTransferVaa,
-  parseVaa,
   redeemOnEth,
   redeemOnSui,
   transferFromEth,
@@ -52,14 +43,12 @@ import {
   getInnerType,
   getPackageId,
   getWrappedCoinType,
-  newEmitterCap,
 } from "../../sui";
 import {
   CHAIN_ID_ETH,
   CHAIN_ID_SUI,
   CONTRACTS,
   hexToUint8Array,
-  parseTransferPayload,
   tryNativeToHexString,
   tryNativeToUint8Array,
 } from "../../utils";
@@ -78,8 +67,6 @@ import {
   mintAndTransferCoinSui,
 } from "./utils/helpers";
 
-jest.setTimeout(120000);
-
 // Sui constants
 const SUI_CORE_BRIDGE_STATE_OBJECT_ID = CONTRACTS.DEVNET.sui.core;
 const SUI_TOKEN_BRIDGE_STATE_OBJECT_ID = CONTRACTS.DEVNET.sui.token_bridge;
@@ -101,7 +88,7 @@ const suiSigner: RawSigner = new RawSigner(suiKeypair, suiProvider);
 const ETH_CORE_BRIDGE_ADDRESS = CONTRACTS.DEVNET.ethereum.core;
 const ETH_TOKEN_BRIDGE_ADDRESS = CONTRACTS.DEVNET.ethereum.token_bridge;
 
-const ethProvider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+const ethProvider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
 const ethSigner = new ethers.Wallet(ETH_PRIVATE_KEY10, ethProvider);
 
 let suiCoreBridgePackageId: string;
@@ -118,10 +105,6 @@ beforeAll(async () => {
   );
 });
 
-afterAll(async () => {
-  await ethProvider.destroy();
-});
-
 // Modify the VAA to only have 1 guardian signature
 // TODO: remove this when we can deploy the devnet core contract
 // deterministically with multiple guardians in the initial guardian set
@@ -165,6 +148,7 @@ describe("Sui SDK tests", () => {
       ETH_CORE_BRIDGE_ADDRESS
     );
     expect(attestSequence).toBeTruthy();
+    await ethProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
     let { vaaBytes: attestVAA }: { vaaBytes: Uint8Array } =
       await getSignedVAAWithRetry(
         WORMHOLE_RPC_HOSTS,
@@ -176,7 +160,6 @@ describe("Sui SDK tests", () => {
         }
       );
     const slicedAttestVAA = sliceVAASignatures(attestVAA);
-    console.log(Buffer.from(slicedAttestVAA).toString("hex"));
     expect(slicedAttestVAA).toBeTruthy();
 
     // Start create wrapped on Sui
@@ -331,6 +314,7 @@ describe("Sui SDK tests", () => {
       transferReceipt,
       ETH_CORE_BRIDGE_ADDRESS
     );
+    await ethProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
     let { vaaBytes: transferFromEthVAA } = await getSignedVAAWithRetry(
       WORMHOLE_RPC_HOSTS,
       CHAIN_ID_ETH,
@@ -381,7 +365,6 @@ describe("Sui SDK tests", () => {
         coinType: coinType,
       })
     ).data;
-    console.log({ coins, coinType });
     const suiTransferTxPayload = await transferFromSui(
       suiProvider,
       SUI_CORE_BRIDGE_STATE_OBJECT_ID,
@@ -495,7 +478,6 @@ describe("Sui SDK tests", () => {
         transport: NodeHttpTransport(),
       }
     );
-    console.log(parseAttestMetaVaa(attestVAA));
     expect(attestVAA).toBeTruthy();
 
     //   // Create wrapped on Ethereum

+ 14 - 21
sdk/js/src/token_bridge/__tests__/terra-integration.ts

@@ -10,12 +10,12 @@ import {
 } from "@terra-money/terra.js";
 import { ethers } from "ethers";
 import {
-  approveEth,
-  attestFromEth,
-  attestFromTerra,
   CHAIN_ID_ETH,
   CHAIN_ID_TERRA,
   CONTRACTS,
+  approveEth,
+  attestFromEth,
+  attestFromTerra,
   createWrappedOnEth,
   createWrappedOnTerra,
   getEmitterAddressEth,
@@ -53,8 +53,6 @@ import {
   waitForTerraExecution,
 } from "./utils/helpers";
 
-jest.setTimeout(120000);
-
 function sleep(ms: number) {
   return new Promise((resolve) => setTimeout(resolve, ms));
 }
@@ -106,7 +104,7 @@ describe("Terra Classic Integration Tests", () => {
             });
             await broadcastAndWait(lcd, tx);
           }
-          const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+          const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
           const signer = new ethers.Wallet(ETH_PRIVATE_KEY4, provider);
           // attempt to transfer more than we've deposited
           const transfer = new MsgExecuteContract(
@@ -186,7 +184,6 @@ describe("Terra Classic Integration Tests", () => {
             fee: feeEstimate,
           });
           await broadcastAndWait(lcd, tx);
-          provider.destroy();
           done();
         } catch (e) {
           console.error(e);
@@ -202,7 +199,7 @@ describe("Terra Classic Integration Tests", () => {
       (async () => {
         try {
           // create a signer for Eth
-          const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+          const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
           const signer = new ethers.Wallet(ETH_PRIVATE_KEY4, provider);
           // attest the test token
           const receipt = await attestFromEth(
@@ -218,6 +215,7 @@ describe("Terra Classic Integration Tests", () => {
           const emitterAddress = getEmitterAddressEth(
             CONTRACTS.DEVNET.ethereum.token_bridge
           );
+          await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
           // poll until the guardian(s) witness and sign the vaa
           const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
             WORMHOLE_RPC_HOSTS,
@@ -265,7 +263,6 @@ describe("Terra Classic Integration Tests", () => {
           } catch (e) {
             // this could fail because the token is already attested (in an unclean env)
           }
-          provider.destroy();
           done();
         } catch (e) {
           console.error(e);
@@ -293,7 +290,7 @@ describe("Terra Classic Integration Tests", () => {
       (async () => {
         try {
           // create a signer for Eth
-          const provider = new ethers.providers.WebSocketProvider(
+          const provider = new ethers.providers.JsonRpcProvider(
             ETH_NODE_URL
           ) as any;
           const signer = new ethers.Wallet(ETH_PRIVATE_KEY4, provider);
@@ -381,6 +378,7 @@ describe("Terra Classic Integration Tests", () => {
           const emitterAddress = getEmitterAddressEth(
             CONTRACTS.DEVNET.ethereum.token_bridge
           );
+          await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
           // poll until the guardian(s) witness and sign the vaa
           const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
             WORMHOLE_RPC_HOSTS,
@@ -451,7 +449,6 @@ describe("Terra Classic Integration Tests", () => {
             tokenDefinition.decimals
           );
           // let finalCW20BalOnTerra: number = parseInt(balAmount);
-          provider.destroy();
           done();
         } catch (e) {
           console.error(e);
@@ -516,7 +513,7 @@ describe("Terra Classic Integration Tests", () => {
             sequence,
             emitterAddress
           );
-          const provider = new ethers.providers.WebSocketProvider(
+          const provider = new ethers.providers.JsonRpcProvider(
             ETH_NODE_URL
           ) as any;
           const signer = new ethers.Wallet(ETH_PRIVATE_KEY4, provider);
@@ -538,7 +535,6 @@ describe("Terra Classic Integration Tests", () => {
             );
             success = true;
           }
-          provider.destroy();
         } catch (e) {
           console.error("Attestation failure: ", e);
         }
@@ -567,7 +563,7 @@ describe("Terra Classic Integration Tests", () => {
           // const initialFeeBalance: number = await queryBalanceOnTerra(FeeAsset);
 
           // Get initial balance of wrapped luna on Eth
-          const provider = new ethers.providers.WebSocketProvider(
+          const provider = new ethers.providers.JsonRpcProvider(
             ETH_NODE_URL
           ) as any;
           const signer = new ethers.Wallet(ETH_PRIVATE_KEY4, provider);
@@ -678,7 +674,6 @@ describe("Terra Classic Integration Tests", () => {
           expect(initialLunaBalOnEthInt + 1e6 === lunaBalOnEthAfterInt).toBe(
             true
           );
-          provider.destroy();
         } catch (e) {
           console.error("Terra to Ethereum failure: ", e);
           done("Terra to Ethereum Failure");
@@ -701,7 +696,7 @@ describe("Terra Classic Integration Tests", () => {
           });
           const Asset: string = "uluna";
           const initialTerraBalance: number = await queryBalanceOnTerra(Asset);
-          const provider = new ethers.providers.WebSocketProvider(
+          const provider = new ethers.providers.JsonRpcProvider(
             ETH_NODE_URL
           ) as any;
           const signer = new ethers.Wallet(ETH_PRIVATE_KEY4, provider);
@@ -755,7 +750,7 @@ describe("Terra Classic Integration Tests", () => {
           const emitterAddress = getEmitterAddressEth(
             CONTRACTS.DEVNET.ethereum.token_bridge
           );
-
+          await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
           // poll until the guardian(s) witness and sign the vaa
           const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
             WORMHOLE_RPC_HOSTS,
@@ -813,7 +808,6 @@ describe("Terra Classic Integration Tests", () => {
             true
           );
           // const uusdBal = await queryBalanceOnTerra("uusd");
-          provider.destroy();
         } catch (e) {
           console.error("Transfer back failure: ", e);
           done("Transfer back Failure");
@@ -890,7 +884,7 @@ describe("Terra Classic Integration Tests", () => {
             sequence,
             emitterAddress
           );
-          const provider = new ethers.providers.WebSocketProvider(
+          const provider = new ethers.providers.JsonRpcProvider(
             ETH_NODE_URL
           ) as any;
           const signer = new ethers.Wallet(ETH_PRIVATE_KEY4, provider);
@@ -1070,7 +1064,7 @@ describe("Terra Classic Integration Tests", () => {
           emitterAddress = getEmitterAddressEth(
             CONTRACTS.DEVNET.ethereum.token_bridge
           );
-
+          await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
           // poll until the guardian(s) witness and sign the vaa
           const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
             WORMHOLE_RPC_HOSTS,
@@ -1132,7 +1126,6 @@ describe("Terra Classic Integration Tests", () => {
           finalCW20BalOnTerra = parseInt(amount);
           expect(finalCW20BalOnTerra - initialCW20BalOnTerra === 1).toBe(true);
           // Done checking wallet balances
-          provider.destroy();
         } catch (e) {
           console.error("CW20 Transfer failure: ", e);
           done("CW20 Transfer Failure");

+ 5 - 7
sdk/js/src/token_bridge/__tests__/terra2-integration.ts

@@ -1,10 +1,10 @@
-import { beforeAll, afterAll, describe, expect, test } from "@jest/globals";
+import { beforeAll, describe, expect, test } from "@jest/globals";
 import {
-  isTxError,
   LCDClient,
   MnemonicKey,
   Msg,
   Wallet,
+  isTxError,
 } from "@terra-money/terra.js";
 import { ethers } from "ethers";
 import { parseUnits } from "ethers/lib/utils";
@@ -61,7 +61,7 @@ const terraClassicWallet = lcdClassic.wallet(
 );
 const terraClassicWalletAddress = terraClassicWallet.key.accAddress;
 
-const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+const provider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
 const signer = new ethers.Wallet(ETH_PRIVATE_KEY2, provider);
 const ethEmitterAddress = getEmitterAddressEth(
   CONTRACTS.DEVNET.ethereum.token_bridge
@@ -78,10 +78,6 @@ beforeAll(async () => {
   );
 });
 
-afterAll(async () => {
-  provider.destroy();
-});
-
 const terraBroadcastAndWaitForExecution = async (
   msgs: Msg[],
   wallet: Wallet,
@@ -179,6 +175,7 @@ describe("Terra Integration Tests", () => {
       signer,
       TEST_ERC20
     );
+    await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
     const attestSignedVaa = await ethParseLogAndGetSignedVaa(attestReceipt);
     const createWrappedMsg = await createWrappedOnTerra(
       CONTRACTS.DEVNET.terra2.token_bridge,
@@ -201,6 +198,7 @@ describe("Terra Integration Tests", () => {
       CHAIN_ID_TERRA2,
       tryNativeToUint8Array(terraWalletAddress, CHAIN_ID_TERRA2)
     );
+    await provider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
     const transferSignedVaa = await ethParseLogAndGetSignedVaa(transferReceipt);
     const redeemMsg = await redeemOnTerra(
       CONTRACTS.DEVNET.terra2.token_bridge,

+ 3 - 4
sdk/js/src/token_bridge/__tests__/utils/consts.ts

@@ -1,10 +1,9 @@
-import { describe, expect, it } from "@jest/globals";
-import { Connection, PublicKey } from "@solana/web3.js";
-
 const ci = !!process.env.CI;
 
 // see devnet.md
-export const ETH_NODE_URL = ci ? "ws://eth-devnet:8545" : "ws://localhost:8545";
+export const ETH_NODE_URL = ci
+  ? "http://eth-devnet:8545"
+  : "http://localhost:8545";
 export const ETH_PRIVATE_KEY =
   "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d"; // account 0
 // account 1 used by NFT tests

+ 11 - 40
wormchain/contracts/tools/__tests__/test_accountant.ts

@@ -52,8 +52,8 @@ const ci = !!process.env.CI;
 const GUARDIAN_HOST = ci ? "guardian" : "localhost";
 const GUARDIAN_RPCS = [`http://${GUARDIAN_HOST}:7071`];
 const GUARDIAN_METRICS = `http://${GUARDIAN_HOST}:6060/metrics`;
-const ETH_NODE_URL = ci ? "ws://eth-devnet:8545" : "ws://localhost:8545";
-const BSC_NODE_URL = ci ? "ws://eth-devnet2:8545" : "ws://localhost:8546";
+const ETH_NODE_URL = ci ? "http://eth-devnet:8545" : "http://localhost:8545";
+const BSC_NODE_URL = ci ? "http://eth-devnet2:8545" : "http://localhost:8546";
 const ETH_PRIVATE_KEY9 =
   "0xb0057716d5917badaf911b193b12b910811c1497b5bada8d7711f758981c3773";
 const ETH_GA_TEST_TOKEN =
@@ -70,25 +70,23 @@ function sleep(ms) {
   return new Promise((resolve) => setTimeout(resolve, ms));
 }
 
-let ethProvider: ethers.providers.WebSocketProvider;
+let ethProvider: ethers.providers.JsonRpcProvider;
 let ethSigner: ethers.Wallet;
-let bscProvider: ethers.providers.WebSocketProvider;
+let bscProvider: ethers.providers.JsonRpcProvider;
 let bscSigner: ethers.Wallet;
 let cosmWasmClient: CosmWasmClient;
 
 beforeAll(async () => {
   // create a signer for Eth
-  ethProvider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+  ethProvider = new ethers.providers.JsonRpcProvider(ETH_NODE_URL);
   ethSigner = new ethers.Wallet(ETH_PRIVATE_KEY9, ethProvider);
   // create a signer for BSC
-  bscProvider = new ethers.providers.WebSocketProvider(BSC_NODE_URL);
+  bscProvider = new ethers.providers.JsonRpcProvider(BSC_NODE_URL);
   bscSigner = new ethers.Wallet(ETH_PRIVATE_KEY9, bscProvider);
   cosmWasmClient = await CosmWasmClient.connect(TENDERMINT_URL);
 });
 
 afterAll(async () => {
-  await ethProvider.destroy();
-  await bscProvider.destroy();
   cosmWasmClient.disconnect();
 });
 
@@ -165,9 +163,8 @@ describe("Global Accountant Tests", () => {
         tryNativeToUint8Array(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH)
       );
       if (attestedAddress && attestedAddress !== ethers.constants.AddressZero) {
-        console.log("already attested");
+        // already attested
       } else {
-        console.log("attesting...");
         // attest the test token
         const receipt = await attestFromEth(
           CONTRACTS.DEVNET.ethereum.token_bridge,
@@ -182,7 +179,7 @@ describe("Global Accountant Tests", () => {
         const emitterAddress = getEmitterAddressEth(
           CONTRACTS.DEVNET.ethereum.token_bridge
         );
-        console.log(`fetching vaa ${sequence}...`);
+        await ethProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
         // poll until the guardian(s) witness and sign the vaa
         const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
           GUARDIAN_RPCS,
@@ -193,7 +190,6 @@ describe("Global Accountant Tests", () => {
             transport: NodeHttpTransport(),
           }
         );
-        console.log("creating...");
         await createWrappedOnEth(
           CONTRACTS.DEVNET.bsc.token_bridge,
           bscSigner,
@@ -225,7 +221,6 @@ describe("Global Accountant Tests", () => {
       );
       const amount = parseUnits("1", DECIMALS);
       // approve the bridge to spend tokens
-      console.log("approving...");
       await approveEth(
         CONTRACTS.DEVNET.ethereum.token_bridge,
         ETH_GA_TEST_TOKEN,
@@ -233,7 +228,6 @@ describe("Global Accountant Tests", () => {
         amount
       );
       // transfer tokens out
-      console.log("transferring...");
       const receipt = await transferFromEth(
         CONTRACTS.DEVNET.ethereum.token_bridge,
         ethSigner,
@@ -250,7 +244,7 @@ describe("Global Accountant Tests", () => {
       const emitterAddress = getEmitterAddressEth(
         CONTRACTS.DEVNET.ethereum.token_bridge
       );
-      console.log(`fetching vaa ${sequence}...`);
+      await ethProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
       // poll until the guardian(s) witness and sign the vaa
       const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
         GUARDIAN_RPCS,
@@ -261,18 +255,12 @@ describe("Global Accountant Tests", () => {
           transport: NodeHttpTransport(),
         }
       );
-      console.log("redeeming...");
       await redeemOnEth(
         CONTRACTS.DEVNET.bsc.token_bridge,
         bscSigner,
         signedVAA
       );
       const afterMetrics = await fetchGlobalAccountantMetrics();
-      console.log(
-        "approved b/a:",
-        beforeMetrics.global_accountant_transfer_vaas_submitted_and_approved,
-        afterMetrics.global_accountant_transfer_vaas_submitted_and_approved
-      );
       if (
         afterMetrics.global_accountant_events_received <=
           beforeMetrics.global_accountant_events_received ||
@@ -333,7 +321,6 @@ describe("Global Accountant Tests", () => {
       );
       const amount = parseUnits("1", DECIMALS);
       // approve the bridge to spend tokens
-      console.log("approving...");
       await approveEth(
         CONTRACTS.DEVNET.bsc.token_bridge,
         attestedAddress,
@@ -341,7 +328,6 @@ describe("Global Accountant Tests", () => {
         amount
       );
       // transfer tokens out
-      console.log("transferring...");
       const receipt = await transferFromEth(
         CONTRACTS.DEVNET.bsc.token_bridge,
         bscSigner,
@@ -358,7 +344,7 @@ describe("Global Accountant Tests", () => {
       const emitterAddress = getEmitterAddressEth(
         CONTRACTS.DEVNET.bsc.token_bridge
       );
-      console.log(`fetching vaa ${sequence}...`);
+      await bscProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
       // poll until the guardian(s) witness and sign the vaa
       const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
         GUARDIAN_RPCS,
@@ -369,18 +355,12 @@ describe("Global Accountant Tests", () => {
           transport: NodeHttpTransport(),
         }
       );
-      console.log("redeeming...");
       await redeemOnEth(
         CONTRACTS.DEVNET.ethereum.token_bridge,
         ethSigner,
         signedVAA
       );
       const afterMetrics = await fetchGlobalAccountantMetrics();
-      console.log(
-        "approved b/a:",
-        beforeMetrics.global_accountant_transfer_vaas_submitted_and_approved,
-        afterMetrics.global_accountant_transfer_vaas_submitted_and_approved
-      );
       if (
         afterMetrics.global_accountant_events_received <=
           beforeMetrics.global_accountant_events_received ||
@@ -428,7 +408,6 @@ describe("Global Accountant Tests", () => {
     // STEP 3a - redeem spoofed tokens
     //
     {
-      console.log("redeeming spoofed tokens");
       let vaa: VAA<TokenBridgeTransfer> = {
         version: 1,
         guardianSetIndex: 0,
@@ -471,7 +450,6 @@ describe("Global Accountant Tests", () => {
       const beforeMetrics = await fetchGlobalAccountantMetrics();
       const amount = parseUnits("9000", DECIMALS);
       // approve the bridge to spend tokens
-      console.log("approving...");
       await approveEth(
         CONTRACTS.DEVNET.bsc.token_bridge,
         attestedAddress,
@@ -479,7 +457,6 @@ describe("Global Accountant Tests", () => {
         amount
       );
       // transfer tokens out
-      console.log("transferring...");
       const receipt = await transferFromEth(
         CONTRACTS.DEVNET.bsc.token_bridge,
         bscSigner,
@@ -492,14 +469,9 @@ describe("Global Accountant Tests", () => {
         receipt,
         CONTRACTS.DEVNET.bsc.core
       );
-      console.log("waiting 30s to fetch metrics...");
+      await bscProvider.send("anvil_mine", ["0x40"]); // 64 blocks should get the above block to `finalized`
       await sleep(30 * 1000); // give the guardian a few seconds to pick up the transfers and attempt to submit them
       const afterMetrics = await fetchGlobalAccountantMetrics();
-      console.log(
-        "balance errors b/a:",
-        beforeMetrics.global_accountant_total_balance_errors,
-        afterMetrics.global_accountant_total_balance_errors
-      );
       if (
         afterMetrics.global_accountant_error_events_received <=
           beforeMetrics.global_accountant_error_events_received ||
@@ -529,6 +501,5 @@ describe("Global Accountant Tests", () => {
         ).rejects.toThrow();
       }
     }
-    console.log("success!");
   });
 });

+ 1 - 1
wormchain/contracts/tools/__tests__/test_ntt_accountant.ts

@@ -1506,7 +1506,7 @@ describe("NTT Global Accountant Tests", () => {
         `0x${mockTransferPayload(8, 10, SPOKE_CHAIN_A)}`,
         0,
         { value },
-        relayerOptionalParameters
+        { ...relayerOptionalParameters, consistencyLevel: 200 }
       );
       const receipt = await tx.wait();
       // get the sequence from the logs (needed to fetch the vaa)

+ 18 - 0
wormchain/contracts/tools/ci-config.js

@@ -0,0 +1,18 @@
+process.env.CI = true;
+
+const info = console.info;
+console.info = function (x) {
+  if (x !== "secp256k1 unavailable, reverting to browser version") {
+    info(x);
+  }
+};
+
+const warn = console.warn;
+console.warn = function (x) {
+  if (
+    x !==
+    "bigint: Failed to load bindings, pure JS will be used (try npm run rebuild?)"
+  ) {
+    warn(x);
+  }
+};

+ 2 - 2
wormchain/contracts/tools/package.json

@@ -5,8 +5,8 @@
   "main": "deploy_wormchain.ts",
   "scripts": {
     "deploy-wormchain": "ts-node deploy_wormchain.ts",
-    "test-accountant": "jest test_accountant.ts --verbose",
-    "test-ntt-accountant": "jest test_ntt_accountant.ts --verbose",
+    "test-accountant": "jest test_accountant.ts --verbose --setupFiles ./ci-config.js",
+    "test-ntt-accountant": "jest test_ntt_accountant.ts --verbose --setupFiles ./ci-config.js",
     "test-wormchain": "ts-node test_wormchain.ts",
     "deploy-and-test": "npm run deploy-wormchain && npm run test-wormchain"
   },

+ 0 - 1
wormchain/ts-sdk/src/core/wallet.ts

@@ -9,7 +9,6 @@ export async function getWallet(
   mnemonic: string,
   options?: DirectSecp256k1HdWalletOptions
 ): Promise<DirectSecp256k1HdWallet> {
-  console.log("wallet");
   const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
     prefix: ADDRESS_PREFIX,
   });