Browse Source

aptos: dockerfile + scripts + README

Csongor Kiss 3 years ago
parent
commit
ffa31da17c

+ 13 - 0
.github/workflows/build.yml

@@ -186,6 +186,19 @@ jobs:
 
 
           cargo test --workspace --features "nft-bridge/instructions token-bridge/instructions wormhole-bridge-solana/instructions"
           cargo test --workspace --features "nft-bridge/instructions token-bridge/instructions wormhole-bridge-solana/instructions"
 
 
+  aptos:
+    name: Aptos
+    runs-on: ubuntu-20.04
+    defaults:
+      run:
+        shell: bash
+        working-directory: ./aptos
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v2
+
+      - name: Run tests via docker
+        run: make test-docker
 
 
   terra:
   terra:
     runs-on: ubuntu-20.04
     runs-on: ubuntu-20.04

+ 2 - 1
.gitignore

@@ -1,6 +1,7 @@
 *.log
 *.log
 build
 build
-node_modules
+**/node_modules
+/aptos/.aptos/**
 .idea
 .idea
 .dccache
 .dccache
 .arcconfig
 .arcconfig

+ 6 - 0
aptos/Docker.md

@@ -0,0 +1,6 @@
+# first build the image
+(cd ..; DOCKER_BUILDKIT=1 docker build -f aptos/Dockerfile.base -t aptos .)
+# tag the image with the appropriate version
+docker tag aptos:latest ghcr.io/wormhole-foundation/aptos:0.3.4
+# push to ghcr
+docker push ghcr.io/wormhole-foundation/aptos:0.3.4

+ 24 - 0
aptos/Dockerfile

@@ -0,0 +1,24 @@
+FROM ghcr.io/wormhole-foundation/aptos:0.4.0@sha256:37ceb6403c1f3ad2728ec0c71acb21a531c71d5156f37fc182f97940c982bfa7 as aptos
+
+# Support additional root CAs
+COPY cert.pem* /certs/
+RUN if [ -e /certs/cert.pem ]; then cp /certs/cert.pem /etc/ssl/certs/ca-certificates.crt; fi
+
+WORKDIR /tmp
+
+COPY wormhole/ wormhole
+COPY token_bridge/ token_bridge
+COPY deployer/ deployer
+COPY coin/ coin
+COPY examples/ examples
+COPY Makefile Makefile
+COPY scripts scripts
+# In this step we optionally copy the .env file too
+COPY start_node.sh .env* .
+
+FROM aptos AS tests
+
+WORKDIR /tmp
+
+RUN --mount=type=cache,target=/root/.move,id=move_cache \
+    make test

+ 23 - 0
aptos/Dockerfile.base

@@ -0,0 +1,23 @@
+FROM rust:1.62@sha256:5777f201f507075309c4d2d1c1e8d8219e654ae1de154c844341050016a64a0c as aptos-node
+
+RUN apt-get update && apt-get -y install libclang-dev jq cmake curl npm --no-install-recommends
+
+WORKDIR /tmp
+
+RUN git clone https://github.com/aptos-labs/aptos-core.git
+WORKDIR /tmp/aptos-core
+RUN cargo build -p aptos --profile cli
+
+FROM rust:1.62@sha256:5777f201f507075309c4d2d1c1e8d8219e654ae1de154c844341050016a64a0c as export-stage
+COPY --from=aptos-node /tmp/aptos-core/target/cli/aptos /usr/local/cargo/bin/aptos
+
+RUN apt-get update && apt-get -y install npm
+WORKDIR /tmp
+RUN npm install -g n typescript ts-node
+RUN n stable
+
+COPY clients/js  /tmp/clients/js
+
+WORKDIR /tmp/clients/js
+
+RUN make install

+ 10 - 0
aptos/Makefile

@@ -0,0 +1,10 @@
+CONTRACT_DIRS := deployer wormhole token_bridge examples coin
+
+TARGETS := build test
+
+.PHONY: $(TARGETS)
+$(TARGETS):
+	$(foreach dir,$(CONTRACT_DIRS), make -C $(dir) $@ &&) true
+
+test-docker:
+	DOCKER_BUILDKIT=1 docker build -f Dockerfile --target tests .

+ 339 - 0
aptos/README.md

@@ -0,0 +1,339 @@
+# Wormhole on Aptos
+
+This folder contains the reference implementation of the Wormhole cross-chain
+messaging protocol smart contracts on the [Aptos](https://aptoslabs.com/)
+blockchain, implemented in the [Move](https://move-book.com/) programming
+language.
+
+# Project structure
+
+The project is laid out as follows:
+
+- [wormhole](./wormhole) the core messaging layer
+- [token_bridge](./token_bridge) the asset transfer layer
+- [examples](./examples) various example contracts
+
+To see a minimal example of how to integrate with wormhole, check out
+[sender.move](./examples/core_messages/sources/sender.move).
+
+# Hacking
+
+The project is under active development, and the development workflow is in
+constant flux, so these steps are subject to change.
+
+## Prerequisites
+
+Install the `aptos` CLI. This tool is used to compile the contracts and run the tests.
+
+``` sh
+$ git clone https://github.com/aptos-labs/aptos-core.git
+$ cd aptos-core
+aptos-core $ cargo build --package aptos --release
+aptos-core $ mv target/release/aptos ~/.cargo/bin/aptos # move the binary to somewhere on your PATH
+```
+
+
+Next, install the [worm](../clients/js/README.md) CLI tool by running
+
+``` sh
+wormhole/clients/js $ make install
+```
+
+
+`worm` is the swiss army knife for interacting with wormhole contracts on all
+supported chains, and generating signed messages (VAAs) for testing.
+
+As an optional, but recommended step, install the
+[move-analyzer](https://github.com/move-language/move/tree/main/language/move-analyzer)
+Language Server (LSP):
+
+``` sh
+cargo install --git https://github.com/move-language/move.git move-analyzer --branch main --features "address32"
+```
+
+Note the `--features "address32"` flag. This is important, because the default
+build only supports 16 byte addresses, but Aptos uses 32 bytes, so
+`move-analyzer` needs to be built with that feature flag to support 32 byte
+address literals.
+
+This installs the LSP backend which is then supported by most popular editors such as [emacs](https://github.com/emacs-lsp/lsp-mode), [vim](https://github.com/neoclide/coc.nvim), and even [vscode](https://marketplace.visualstudio.com/items?itemName=move.move-analyzer).
+
+<details>
+    <summary>For emacs, you may need to add the following to your config file:</summary>
+
+``` lisp
+;; Move
+(define-derived-mode move-mode rust-mode "Move"
+  :group 'move-mode)
+
+(add-to-list 'auto-mode-alist '("\\.move\\'" . move-mode))
+
+(with-eval-after-load 'lsp-mode
+  (add-to-list 'lsp-language-id-configuration
+    '(move-mode . "move"))
+
+  (lsp-register-client
+    (make-lsp-client :new-connection (lsp-stdio-connection "move-analyzer")
+                     :activation-fn (lsp-activate-on "move")
+                     :server-id 'move-analyzer)))
+```
+
+</details>
+
+## Building & running tests
+
+The project uses a simple `make`-based build system for building and running
+tests. Running `make test` in this directory will run the tests for each
+contract. If you only want to run the tests for, say, the token bridge contract,
+then you can run `make test` in the `token_bridge` directory, or run `make -C
+token_bridge test` from this directory.
+
+Additionally, `make test-docker` runs the tests in a docker container which is
+set up with all the necessary dependencies. This is the command that runs in CI.
+
+## Running a local validator and deploying the contracts to it
+
+Simply run
+
+``` sh
+worm start-validator aptos
+```
+
+which will start a local aptos validator with an RPC endpoint at `0.0.0.0:8080`
+and the faucet endpoint at `0.0.0.0:8081`. Note that the faucet takes a few
+(~10) seconds to come up, so only proceed when you see the following:
+
+``` text
+Faucet is running.  Faucet endpoint: 0.0.0.0:8081
+```
+
+
+Once the validator is running, the contracts are ready to deploy. In the
+[scripts](./scripts) directory, run
+
+``` sh
+scripts $ ./deploy
+```
+
+This will deploy the core contract, the token bridge, and an example contract
+for sending messages through wormhole.
+
+When you make a change to the contract, you can simply restart the validator and
+run the deploy script again. However, a better way is to run one of the following scripts:
+
+``` sh
+scripts $ ./upgrade devnet Core # for upgrading the wormhole contract
+scripts $ ./upgrade devnet TokenBridge # for upgarding the token bridge contract
+```
+
+Behind the scenes, these scripts exercise the whole contract upgrade code path
+(see below), including generating and verifying a signed governance action, and
+the Move bytecode verifier checking ABI compatibility. If an upgrade here fails
+due to incompatibility, it will likely on mainnet too. (TODO: add CI action to
+simulate upgrades against dev.v2 when there's a stable version)
+
+# Implementation notes / coding practices
+
+In this section, we describe some of the implementation design decisions and
+coding practices we converged on along the way. Note that the coding guidelines
+are prescriptive rather than descriptive, and the goal is for the contracts to
+ultimately follow these, but they might not during earlier development phases.
+
+## Signers
+
+In Move, each entry point function may take an optional first argument of type
+`signer` or `&signer`, as follows
+
+``` rust
+public entry fun foo(user: &signer) {
+  // do stuff
+}
+```
+
+When a user signs a transaction that calls `foo`, their wallet will effectively
+be passed in as a `signer` to `foo`. This `signer` value can then be used to
+authorise *arbitrary* actions on behalf of the user, such as withdrawing their
+coins:
+
+``` rust
+use aptos_framework::coin;
+use aptos_framework::aptos_coin::AptosCoin;
+
+public entry fun foo(user: &signer) {
+    let coins = coin::withdraw<AptosCoin>(user, 100);
+
+    // ...
+}
+```
+
+The `user` value can even be passed on to other functions down the call stack,
+so the user has to fully trust `foo` and potentially understand its
+implementation to be sure that the transaction is safe to sign. Since the
+`signer` object can be passed arbitrarily deep into the call stack, tracing the
+exact path is onerous. This hurts composability too, because composing contracts
+that take `signer`s now places additional burden on each caller to ensure that
+the callee contract is non-malicious and trust that it won't turn malicious in
+the future through an upgrade. Thus we consider taking `signer` arguments an
+*anti-pattern*, and avoid it wherever possible.
+
+Here, `foo` requires the user's `signer` to be able to withdraw 100 aptos coins.
+A clearer and safer way to achieve this is by writing `foo` in the following way:
+
+``` rust
+use aptos_framework::coin::{Self, Coin};
+use aptos_framework::aptos_coin::AptosCoin;
+
+public entry fun foo(coins: Coin<AptosCoin>) {
+    assert!(coin::value(&coins) == 100, SOME_ERROR_CODE);
+
+    // ...
+}
+```
+
+Just the type of this version itself makes it extremely clear what `foo` really
+needs, and before calling this function the caller can just withdraw their coins
+themselves. As a convenience function, we may introduce a wrapper that _does_
+take a signer:
+
+``` rust
+public entry fun foo_with_signer(user: &signer) {
+    foo(coin::withdraw(user, 100))
+}
+```
+
+which might be the preferred version for EOAs (externally owned accounts, aka
+user wallets), but never for other contracts.
+
+The general rule of thumb is that a function that takes a `signer` should never
+pass that `signer` on to another function (except standard library functions
+like `coin::withdraw`). This way, deciding the safety of a function becomes much
+simpler for users and integrators.
+
+## Access control: fine-grained capabilities
+
+`signer` objects can also be used for access control, because the existence of a
+`signer` value with a given address proves that the address authorised that
+transaction. The key observation is that a `signer` is an unforgable token of
+authority, also known as a _capability_. The issue is, as described in the above
+section, is that the `signer` capability is too general, as it can authorise
+arbitrary actions on behalf of the user. For this reason, we don't use `signer`s
+to implement access control, and instead turn to more fine-grained capabilities.
+
+Thanks to Move's module system and linear type system, it is possible to
+implement first-class capabilities, i.e. non-forgeable objects of authority. For
+example, when sending a message, the wormhole contract needs to record the
+identity of the message sender in a way that cannot be forged by malicious
+actors. A potential solution would be to simply take the sender's `signer`
+object and encode its address into the message:
+
+``` rust
+public fun publish_message(
+    sender: &signer,
+    nonce: u64,
+    payload: vector<u8>,
+    message_fee: Coin<AptosCoin>
+): u64 {
+// ...
+}
+```
+
+However, again, this is not a great solution because the sender now needs to
+fully trust `publish_message`. Instead, we define a capability called
+`EmitterCapability` and require that instead:
+
+``` rust
+public fun publish_message(
+    emitter_cap: &mut emitter::EmitterCapability,
+    nonce: u64,
+    payload: vector<u8>,
+    message_fee: Coin<AptosCoin>
+): u64 {
+```
+
+The `EmitterCapability` type is defined in
+[emitter.move](./wormhole/sources/emitter.move)
+as
+
+``` rust
+struct EmitterCapability has store {
+    emitter: u128,
+    sequence: u64
+}
+```
+
+note that it has no `drop` or `copy` abilities, only `store`, which means that
+once created, the object cannot be destroyed or copied, but it can be stored in
+the storage space of a smart contract. Before being able to send messages
+through wormhole, integrators must obtain such an `EmitterCapability` by calling
+
+``` rust
+public fun register_emitter(): emitter::EmitterCapability
+```
+
+in `./wormhole/sources/wormhole.move`. Note that this function does not take any
+arguments (in particular no signer), and returns an `EmitterCapability`. The
+contract can then store this and use as a unique identifier in the future when
+sending messages through wormhole. Since the wormhole contract is the only
+entity that can create new `EmitterCapability` objects (protected by a similar
+capability mechanism, see the [emitter.move](./wormhole/source/emitter.move)
+module for more details), it can guarantee that the `emitter` field is globally
+unique for each new emitter.
+
+An important safety property of Move is that structs (like `EmitterCapability`)
+are fully opaque outside of the module that defines them. This means that
+there's no way to introspect, modify, or transfer them outside of the defining
+module.  In turn, the defining module may choose to expose an API that provides
+restricted access to the contents. For example,
+[emitter.move](./wormhole/source/emitter.move) defines a getter function for the
+`emitter` field:
+
+``` rust
+public fun get_emitter(emitter_cap: &EmitterCapability): u128 {
+    emitter_cap.emitter
+}
+```
+
+notice the `emitter_cap.emitter` field accessor syntax, which is only legal in
+the defining module of the struct. The only way to access the `sequence` field
+is the following function:
+
+``` rust
+public(friend) fun use_sequence(emitter_cap: &mut EmitterCapability): u64 {
+    let sequence = emitter_cap.sequence;
+    emitter_cap.sequence = sequence + 1;
+    sequence
+}
+```
+
+That is, the emitter capability's sequence counter can only be incremented
+outside of this module, but not modified arbitrarily. As a further security
+measure, this function is marked as `public(friend)`, which means it's only
+accessible from modules that are declared as a "friend" of the `emitter` module.
+
+In practice, the `public_message` function will call this function to get and
+increment the sequence number each time a message is sent.
+
+The fact that the caller can produce a reference to an `EmitterCapability` is
+proof that either they have direct access to the storage that owns it, or they
+have been passed the reference from the actual owner. This pattern enables
+better composability: `EmitterCapability` objects can be transferred in case a
+non-upgradeable contract wants to migrate to a new version but still be able to
+reuse the same wormhole emitter identity. They can also be passed by reference
+down the callstack (through borrowing), which makes it possible for a contract
+to send a message on behalf of another contract *with explicit permission*,
+since the caller contract needs to pass in the reference. It is also possible
+for a single application to have multiple emitter identities at the same time,
+which uncovers new use cases that have not been easily possible in other chains.
+
+## Contract deployment/upgrades
+
+In order to support security patches and new features, the wormhole contracts
+implement upgradeability through governance. For this to be possible without one
+single entity having full control over the contracts, the contracts need to be
+their own signing authority. For details on how this is implemented, see
+[deployer.move](./deployer/sources/deployer.move) and
+[contract_upgrade.move](./wormhole/sources/contract_upgrade.move).
+
+## Newtypes
+
+TODO

+ 51 - 0
aptos/scripts/README.md

@@ -0,0 +1,51 @@
+
+Install `aptos` CLI by running
+```shell
+cargo install --git https://github.com/aptos-labs/aptos-core.git aptos --rev 8ba12c5badeb68d8ff4625a32aceb9043398b16b
+```
+
+Install `worm` CLI by running
+```
+wormhole/clients/js $ make install
+```
+
+## Development workflow
+
+NOTE: this is in flux and likely will change often, so look back here every now
+and then.
+
+First start the local aptos validator by running
+
+``` shell
+worm start-validator aptos
+```
+
+Then build & deploy the contracts
+
+``` shell
+./deploy
+```
+
+At this point you can send messages by running
+
+``` shell
+ts-node publish_wormhole_message.ts
+```
+
+### Upgrades
+
+Make a change to the contract, then rebuild and run the upgrade script:
+
+``` shell
+./upgrade devnet Core
+```
+
+### RPC
+
+https://fullnode.devnet.aptoslabs.com/v1/spec#/operations/get_events_by_event_handle
+
+``` shell
+curl --request GET --header 'Content-Type: application/json'  --url 'http://localhost:8080/v1/accounts/277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b/events/0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b::state::WormholeMessageHandle/event?start=0' | jq
+```
+
+

+ 16 - 0
aptos/scripts/constants.ts

@@ -0,0 +1,16 @@
+import {AptosAccountObject} from "aptos";
+
+export const aptosCoin = {
+    address: "0x1",
+    module: "coin",
+    name: "CoinStore",
+    generic_type_params: ["0x1::aptos_coin::AptosCoin"],
+  };
+
+export const aptosAccountObject: AptosAccountObject = {
+    address: "277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b",
+    privateKeyHex:
+      // eslint-disable-next-line max-len
+      "0x537c1f91e56891445b491068f519b705f8c0f1a1e66111816dd5d4aa85b8113d",
+    publicKeyHex: "0xc5480140ac6c98414dcbd9b19110d9af1847c315e371407749462c82f00e34e8",
+  };

+ 31 - 0
aptos/scripts/deploy

@@ -0,0 +1,31 @@
+#!/bin/bash
+
+set -euo pipefail
+
+GUARDIAN_ADDR=0xbeFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe
+WORMHOLE_ADDR=$(worm contract devnet aptos Core)
+TOKEN_BRIDGE_ADDR=$(worm contract devnet aptos TokenBridge)
+DEPLOYER_ADDR=0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b
+
+NAMED_ADDRS="wormhole=$WORMHOLE_ADDR,deployer=$DEPLOYER_ADDR,token_bridge=$TOKEN_BRIDGE_ADDR"
+
+worm aptos faucet
+
+# Deploy deployer contract for creating resource accounts
+worm aptos deploy --network devnet ../deployer --named-addresses "$NAMED_ADDRS"
+
+# Deploy wormhole
+worm aptos deploy-resource wormhole --network devnet ../wormhole --named-addresses "$NAMED_ADDRS"
+# Initialise wormhole
+worm aptos init-wormhole --network devnet -g $GUARDIAN_ADDR --contract-address "$WORMHOLE_ADDR"
+
+# Deploy & initialise (with `init_module`) token_bridge
+worm aptos deploy-resource token_bridge --network devnet ../token_bridge --named-addresses "$NAMED_ADDRS"
+# Initialise token-bridge
+worm aptos init-token-bridge --network devnet --contract-address "$TOKEN_BRIDGE_ADDR"
+
+# Deploy example program for sending messages
+worm aptos deploy --network devnet ../examples/core_messages --named-addresses "$NAMED_ADDRS"
+
+# Deploy coin
+#worm aptos deploy --network devnet ../wormhole --named-addresses $NAMED_ADDRS

+ 37 - 0
aptos/scripts/deploy_testnet

@@ -0,0 +1,37 @@
+#!/bin/bash
+
+set -euo pipefail
+
+# TODO: merge this with the ./deploy script (like ./upgrade)
+
+DEPLOYER_ADDR=0x5ad53ef0cb7cd21816a0371c367be38e7874a9d2f71c77af7592f6b0791f6ca3
+GUARDIAN_ADDR=0x13947Bd48b18E53fdAeEe77F3473391aC727C638
+WORMHOLE_ADDR=$(worm contract testnet aptos Core)
+TOKEN_BRIDGE_ADDR=$(worm contract testnet aptos TokenBridge)
+
+NAMED_ADDRS="wormhole=$WORMHOLE_ADDR,deployer=$DEPLOYER_ADDR,token_bridge=$TOKEN_BRIDGE_ADDR"
+
+# STEP 1) if deployer address is not funded with Aptos tokens,
+#         first fund it using a faucet script or the Aptos CLI
+worm aptos faucet --rpc 'https://fullnode.testnet.aptoslabs.com/v1' --account $DEPLOYER_ADDR --faucet 'https://faucet.testnet.aptoslabs.com'
+
+#================================================================================================
+
+# Deploy deployer contract for creating resource accounts
+worm aptos deploy --network testnet ../deployer --named-addresses "$NAMED_ADDRS"
+#
+# # Deploy wormhole
+worm aptos deploy-resource wormhole --network testnet ../wormhole --named-addresses "$NAMED_ADDRS"
+#
+# # Initialise wormhole
+worm aptos init-wormhole --network testnet -g $GUARDIAN_ADDR --contract-address $WORMHOLE_ADDR
+
+# Deploy & initialise (with `init_module`) token_bridge
+worm aptos deploy-resource token_bridge --network testnet ../token_bridge --named-addresses "$NAMED_ADDRS"
+
+# Initialise token-bridge
+worm aptos init-token-bridge --network testnet --contract-address $TOKEN_BRIDGE_ADDR
+
+# Deploy example program for sending messages
+# TODO: this does not have the testnet deploy option
+worm aptos deploy --network testnet ../examples/core_messages --named-addresses "$NAMED_ADDRS"

+ 6 - 0
aptos/scripts/generate_new_account.ts

@@ -0,0 +1,6 @@
+import { AptosAccount, TxnBuilderTypes, BCS, AptosClient, FaucetClient } from "aptos";
+
+// generate new account and print private key
+const new_account = new AptosAccount();
+let p = new_account.toPrivateKeyObject();
+console.log("new account object: ", p);

+ 929 - 0
aptos/scripts/package-lock.json

@@ -0,0 +1,929 @@
+{
+  "name": "scripts",
+  "version": "1.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "scripts",
+      "version": "1.0.0",
+      "license": "MIT",
+      "dependencies": {
+        "aptos": "^1.3.9",
+        "nvm": "^0.0.4",
+        "ts-node": "^10.9.1",
+        "typescript": "^4.7.4"
+      },
+      "devDependencies": {
+        "@types/node": "^18.7.13"
+      }
+    },
+    "node_modules/@cspotcode/source-map-support": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+      "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+      "dependencies": {
+        "@jridgewell/trace-mapping": "0.3.9"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.14",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+      "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.9",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+      "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.0.3",
+        "@jridgewell/sourcemap-codec": "^1.4.10"
+      }
+    },
+    "node_modules/@noble/hashes": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz",
+      "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://paulmillr.com/funding/"
+        }
+      ]
+    },
+    "node_modules/@scure/base": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
+      "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://paulmillr.com/funding/"
+        }
+      ]
+    },
+    "node_modules/@scure/bip39": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz",
+      "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://paulmillr.com/funding/"
+        }
+      ],
+      "dependencies": {
+        "@noble/hashes": "~1.1.1",
+        "@scure/base": "~1.1.0"
+      }
+    },
+    "node_modules/@tsconfig/node10": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
+      "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA=="
+    },
+    "node_modules/@tsconfig/node12": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+      "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="
+    },
+    "node_modules/@tsconfig/node14": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+      "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="
+    },
+    "node_modules/@tsconfig/node16": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
+      "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ=="
+    },
+    "node_modules/@types/node": {
+      "version": "18.7.13",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz",
+      "integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw=="
+    },
+    "node_modules/acorn": {
+      "version": "8.8.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+      "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-walk": {
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+      "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/aptos": {
+      "version": "1.3.9",
+      "resolved": "https://registry.npmjs.org/aptos/-/aptos-1.3.9.tgz",
+      "integrity": "sha512-x/h2MEprUu1/gxAvKR7DGqIXT85S2hsXDVXNcstfob0OUtgybnUTf4N7KwjTrQF1XhcmTPcH7Bj7xD6Jb9OWcw==",
+      "dependencies": {
+        "@scure/bip39": "^1.1.0",
+        "axios": "^0.27.2",
+        "buffer": "^6.0.3",
+        "ed25519-hd-key": "^1.2.0",
+        "js-sha3": "^0.8.0",
+        "tweetnacl": "^1.0.3",
+        "typescript-memoize": "^1.1.0",
+        "yarn": "^1.22.19"
+      },
+      "engines": {
+        "node": ">=11.0.0"
+      }
+    },
+    "node_modules/arg": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+      "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+    },
+    "node_modules/axios": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+      "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+      "dependencies": {
+        "follow-redirects": "^1.14.9",
+        "form-data": "^4.0.0"
+      }
+    },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/buffer": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+      "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.2.1"
+      }
+    },
+    "node_modules/cipher-base": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+      "dependencies": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/create-hash": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+      "dependencies": {
+        "cipher-base": "^1.0.1",
+        "inherits": "^2.0.1",
+        "md5.js": "^1.3.4",
+        "ripemd160": "^2.0.1",
+        "sha.js": "^2.4.0"
+      }
+    },
+    "node_modules/create-hmac": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+      "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+      "dependencies": {
+        "cipher-base": "^1.0.3",
+        "create-hash": "^1.1.0",
+        "inherits": "^2.0.1",
+        "ripemd160": "^2.0.0",
+        "safe-buffer": "^5.0.1",
+        "sha.js": "^2.4.8"
+      }
+    },
+    "node_modules/create-require": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+      "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/diff": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+      "engines": {
+        "node": ">=0.3.1"
+      }
+    },
+    "node_modules/ed25519-hd-key": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/ed25519-hd-key/-/ed25519-hd-key-1.3.0.tgz",
+      "integrity": "sha512-IWwAyiiuJQhgu3L8NaHb68eJxTu2pgCwxIBdgpLJdKpYZM46+AXePSVTr7fkNKaUOfOL4IrjEUaQvyVRIDP7fg==",
+      "dependencies": {
+        "create-hmac": "1.1.7",
+        "tweetnacl": "1.0.3"
+      }
+    },
+    "node_modules/follow-redirects": {
+      "version": "1.15.1",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
+      "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/hash-base": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+      "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+      "dependencies": {
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.6.0",
+        "safe-buffer": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/ieee754": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "node_modules/js-sha3": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
+      "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
+    },
+    "node_modules/make-error": {
+      "version": "1.3.6",
+      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+      "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
+    },
+    "node_modules/md5.js": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+      "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+      "dependencies": {
+        "hash-base": "^3.0.0",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/nvm": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/nvm/-/nvm-0.0.4.tgz",
+      "integrity": "sha512-jvmyELykYcdyd0VCGY0E8Aqe5MngEasVvlPvrcJHbwBMUbVqa72mPdQuPzyTcykEtEx7jDrMY0QA5MoV+8EhgA==",
+      "deprecated": "This is NOT the correct nvm. Visit https://nvm.sh and use the curl command to install it.",
+      "bin": {
+        "nvm": "bin/nvm"
+      }
+    },
+    "node_modules/readable-stream": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/ripemd160": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+      "dependencies": {
+        "hash-base": "^3.0.0",
+        "inherits": "^2.0.1"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/sha.js": {
+      "version": "2.4.11",
+      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+      "dependencies": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      },
+      "bin": {
+        "sha.js": "bin.js"
+      }
+    },
+    "node_modules/string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "dependencies": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "node_modules/ts-node": {
+      "version": "10.9.1",
+      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
+      "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
+      "dependencies": {
+        "@cspotcode/source-map-support": "^0.8.0",
+        "@tsconfig/node10": "^1.0.7",
+        "@tsconfig/node12": "^1.0.7",
+        "@tsconfig/node14": "^1.0.0",
+        "@tsconfig/node16": "^1.0.2",
+        "acorn": "^8.4.1",
+        "acorn-walk": "^8.1.1",
+        "arg": "^4.1.0",
+        "create-require": "^1.1.0",
+        "diff": "^4.0.1",
+        "make-error": "^1.1.1",
+        "v8-compile-cache-lib": "^3.0.1",
+        "yn": "3.1.1"
+      },
+      "bin": {
+        "ts-node": "dist/bin.js",
+        "ts-node-cwd": "dist/bin-cwd.js",
+        "ts-node-esm": "dist/bin-esm.js",
+        "ts-node-script": "dist/bin-script.js",
+        "ts-node-transpile-only": "dist/bin-transpile.js",
+        "ts-script": "dist/bin-script-deprecated.js"
+      },
+      "peerDependencies": {
+        "@swc/core": ">=1.2.50",
+        "@swc/wasm": ">=1.2.50",
+        "@types/node": "*",
+        "typescript": ">=2.7"
+      },
+      "peerDependenciesMeta": {
+        "@swc/core": {
+          "optional": true
+        },
+        "@swc/wasm": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tweetnacl": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
+      "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
+    },
+    "node_modules/typescript": {
+      "version": "4.7.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+      "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=4.2.0"
+      }
+    },
+    "node_modules/typescript-memoize": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/typescript-memoize/-/typescript-memoize-1.1.0.tgz",
+      "integrity": "sha512-LQPKVXK8QrBBkL/zclE6YgSWn0I8ew5m0Lf+XL00IwMhlotqRLlzHV+BRrljVQIc+NohUAuQP7mg4HQwrx5Xbg=="
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+    },
+    "node_modules/v8-compile-cache-lib": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+      "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
+    },
+    "node_modules/yarn": {
+      "version": "1.22.19",
+      "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.19.tgz",
+      "integrity": "sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ==",
+      "hasInstallScript": true,
+      "bin": {
+        "yarn": "bin/yarn.js",
+        "yarnpkg": "bin/yarn.js"
+      },
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/yn": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+      "engines": {
+        "node": ">=6"
+      }
+    }
+  },
+  "dependencies": {
+    "@cspotcode/source-map-support": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+      "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+      "requires": {
+        "@jridgewell/trace-mapping": "0.3.9"
+      }
+    },
+    "@jridgewell/resolve-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="
+    },
+    "@jridgewell/sourcemap-codec": {
+      "version": "1.4.14",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+      "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
+    },
+    "@jridgewell/trace-mapping": {
+      "version": "0.3.9",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+      "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+      "requires": {
+        "@jridgewell/resolve-uri": "^3.0.3",
+        "@jridgewell/sourcemap-codec": "^1.4.10"
+      }
+    },
+    "@noble/hashes": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz",
+      "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA=="
+    },
+    "@scure/base": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
+      "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA=="
+    },
+    "@scure/bip39": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz",
+      "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==",
+      "requires": {
+        "@noble/hashes": "~1.1.1",
+        "@scure/base": "~1.1.0"
+      }
+    },
+    "@tsconfig/node10": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
+      "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA=="
+    },
+    "@tsconfig/node12": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+      "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="
+    },
+    "@tsconfig/node14": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+      "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="
+    },
+    "@tsconfig/node16": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
+      "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ=="
+    },
+    "@types/node": {
+      "version": "18.7.13",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz",
+      "integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw=="
+    },
+    "acorn": {
+      "version": "8.8.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+      "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w=="
+    },
+    "acorn-walk": {
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+      "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA=="
+    },
+    "aptos": {
+      "version": "1.3.9",
+      "resolved": "https://registry.npmjs.org/aptos/-/aptos-1.3.9.tgz",
+      "integrity": "sha512-x/h2MEprUu1/gxAvKR7DGqIXT85S2hsXDVXNcstfob0OUtgybnUTf4N7KwjTrQF1XhcmTPcH7Bj7xD6Jb9OWcw==",
+      "requires": {
+        "@scure/bip39": "^1.1.0",
+        "axios": "^0.27.2",
+        "buffer": "^6.0.3",
+        "ed25519-hd-key": "^1.2.0",
+        "js-sha3": "^0.8.0",
+        "tweetnacl": "^1.0.3",
+        "typescript-memoize": "^1.1.0",
+        "yarn": "^1.22.19"
+      }
+    },
+    "arg": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+      "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+    },
+    "axios": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+      "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+      "requires": {
+        "follow-redirects": "^1.14.9",
+        "form-data": "^4.0.0"
+      }
+    },
+    "base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+    },
+    "buffer": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+      "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+      "requires": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.2.1"
+      }
+    },
+    "cipher-base": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+      "requires": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
+    "create-hash": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+      "requires": {
+        "cipher-base": "^1.0.1",
+        "inherits": "^2.0.1",
+        "md5.js": "^1.3.4",
+        "ripemd160": "^2.0.1",
+        "sha.js": "^2.4.0"
+      }
+    },
+    "create-hmac": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+      "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+      "requires": {
+        "cipher-base": "^1.0.3",
+        "create-hash": "^1.1.0",
+        "inherits": "^2.0.1",
+        "ripemd160": "^2.0.0",
+        "safe-buffer": "^5.0.1",
+        "sha.js": "^2.4.8"
+      }
+    },
+    "create-require": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+      "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+    },
+    "diff": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
+    },
+    "ed25519-hd-key": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/ed25519-hd-key/-/ed25519-hd-key-1.3.0.tgz",
+      "integrity": "sha512-IWwAyiiuJQhgu3L8NaHb68eJxTu2pgCwxIBdgpLJdKpYZM46+AXePSVTr7fkNKaUOfOL4IrjEUaQvyVRIDP7fg==",
+      "requires": {
+        "create-hmac": "1.1.7",
+        "tweetnacl": "1.0.3"
+      }
+    },
+    "follow-redirects": {
+      "version": "1.15.1",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
+      "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
+    },
+    "form-data": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+      "requires": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "mime-types": "^2.1.12"
+      }
+    },
+    "hash-base": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+      "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+      "requires": {
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.6.0",
+        "safe-buffer": "^5.2.0"
+      }
+    },
+    "ieee754": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "js-sha3": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
+      "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
+    },
+    "make-error": {
+      "version": "1.3.6",
+      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+      "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
+    },
+    "md5.js": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+      "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+      "requires": {
+        "hash-base": "^3.0.0",
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.1.2"
+      }
+    },
+    "mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+    },
+    "mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "requires": {
+        "mime-db": "1.52.0"
+      }
+    },
+    "nvm": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/nvm/-/nvm-0.0.4.tgz",
+      "integrity": "sha512-jvmyELykYcdyd0VCGY0E8Aqe5MngEasVvlPvrcJHbwBMUbVqa72mPdQuPzyTcykEtEx7jDrMY0QA5MoV+8EhgA=="
+    },
+    "readable-stream": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+      "requires": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      }
+    },
+    "ripemd160": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+      "requires": {
+        "hash-base": "^3.0.0",
+        "inherits": "^2.0.1"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+    },
+    "sha.js": {
+      "version": "2.4.11",
+      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+      "requires": {
+        "inherits": "^2.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "requires": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "ts-node": {
+      "version": "10.9.1",
+      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
+      "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
+      "requires": {
+        "@cspotcode/source-map-support": "^0.8.0",
+        "@tsconfig/node10": "^1.0.7",
+        "@tsconfig/node12": "^1.0.7",
+        "@tsconfig/node14": "^1.0.0",
+        "@tsconfig/node16": "^1.0.2",
+        "acorn": "^8.4.1",
+        "acorn-walk": "^8.1.1",
+        "arg": "^4.1.0",
+        "create-require": "^1.1.0",
+        "diff": "^4.0.1",
+        "make-error": "^1.1.1",
+        "v8-compile-cache-lib": "^3.0.1",
+        "yn": "3.1.1"
+      }
+    },
+    "tweetnacl": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
+      "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
+    },
+    "typescript": {
+      "version": "4.7.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+      "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ=="
+    },
+    "typescript-memoize": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/typescript-memoize/-/typescript-memoize-1.1.0.tgz",
+      "integrity": "sha512-LQPKVXK8QrBBkL/zclE6YgSWn0I8ew5m0Lf+XL00IwMhlotqRLlzHV+BRrljVQIc+NohUAuQP7mg4HQwrx5Xbg=="
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+    },
+    "v8-compile-cache-lib": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+      "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
+    },
+    "yarn": {
+      "version": "1.22.19",
+      "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.19.tgz",
+      "integrity": "sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ=="
+    },
+    "yn": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
+    }
+  }
+}

+ 15 - 0
aptos/scripts/package.json

@@ -0,0 +1,15 @@
+{
+  "name": "scripts",
+  "version": "1.0.0",
+  "main": "index.js",
+  "license": "MIT",
+  "dependencies": {
+    "aptos": "^1.3.9",
+    "nvm": "^0.0.4",
+    "ts-node": "^10.9.1",
+    "typescript": "^4.7.4"
+  },
+  "devDependencies": {
+    "@types/node": "^18.7.13"
+  }
+}

+ 56 - 0
aptos/scripts/publish_wormhole_message.ts

@@ -0,0 +1,56 @@
+import { AptosAccount, TxnBuilderTypes, BCS, HexString, AptosClient } from "aptos";
+import {aptosAccountObject} from "./constants";
+export const NODE_URL = "http://0.0.0.0:8080/v1";
+
+const client = new AptosClient(NODE_URL);
+
+async function publishWormholeMessage(contractAddress: HexString, accountFrom: AptosAccount): Promise<string> {
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        // Send using the sender example program
+        `${contractAddress.toString()}::sender`,
+        "send_message",
+        [],
+        [
+         BCS.bcsSerializeBytes(Buffer.from("hi my name is bob")), // payload
+        ]
+      ),
+    );
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000), //max gas to be used
+      BigInt(1), //price per unit gas
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+
+    const sim = await client.simulateTransaction(accountFrom, rawTxn);
+    sim.forEach((tx) => {
+      if (!tx.success) {
+        console.error(JSON.stringify(tx, null, 2));
+        throw new Error(`Transaction failed: ${tx.vm_status}`);
+      }
+    });
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+
+    return transactionRes.hash;
+  }
+
+  async function main(){
+    let accountFrom = AptosAccount.fromAptosAccountObject(aptosAccountObject)
+    let hash = await publishWormholeMessage(accountFrom.address(), accountFrom);
+    console.log("tx hash: ", hash);
+  }
+
+  if (require.main === module) {
+    main().then((resp) => console.log(resp));
+  }
+
+

+ 93 - 0
aptos/scripts/read.ts

@@ -0,0 +1,93 @@
+import { AptosAccount, TxnBuilderTypes, BCS, HexString, MaybeHexString, AptosClient, FaucetClient, AptosAccountObject} from "aptos";
+import {aptosAccountObject} from "./constants";
+
+export const NODE_URL = "http://0.0.0.0:8080/v1";
+export const FAUCET_URL = "http://localhost:8081";
+
+const {
+  AccountAddress,
+  TypeTagStruct,
+  EntryFunction,
+  StructTag,
+  TransactionPayloadEntryFunction,
+  RawTransaction,
+  ChainId,
+} = TxnBuilderTypes;
+
+//<:!:section_2
+//:!:>section_3
+const client = new AptosClient(NODE_URL);
+
+async function getWormholeState(contractAddress: HexString, accountAddress: MaybeHexString): Promise<any> {
+    try {
+      const resource = await client.getAccountResource(
+        accountAddress,
+        `${contractAddress.toString()}::State::WormholeState`,
+      );
+      return resource;
+    } catch (_) {
+      return "";
+    }
+}
+
+async function getResources(accountAddress: MaybeHexString): Promise<any>{
+    try {
+      const resources = await client.getAccountResources(
+        accountAddress
+      );
+      return resources;
+    } catch (_) {
+      return "";
+    }
+}
+
+async function getTransaction(hash: string) {
+    try {
+      const txs = await client.getTransactionByHash(hash);
+      console.log("getTransactions:transactions: ", txs)
+      return txs;
+    } catch (_) {
+      return "";
+    }
+}
+
+// async function getWormholeEvents(accountAddress: MaybeHexString, handle: any, fieldName: string,){
+//   //@ts-ignore
+//   let events = await client.getEventsByEventHandle(accountAddress, handle, fieldName);
+//   return events
+// }
+
+  async function main(){
+    let accountFrom = AptosAccount.fromAptosAccountObject(aptosAccountObject)
+    let accountAddress = accountFrom.address();
+
+    //resources
+    let resources = await getResources(accountAddress);
+    console.log("resources: ", resources);
+
+    //events
+    //let handle = new TypeTagStruct(StructTag.fromString(`${accountAddress.toString()}::State::WormholeMessageHandle`));
+    // let handle = `${accountAddress.toString()}::State::WormholeMessageHandle`
+    // console.log("handle: ", handle)
+    // let fieldName = "event"
+    // let events = await client.getEventsByEventHandle(accountAddress, handle, fieldName);
+    // console.log("wormhole message publish events: ", events)
+
+    //get specific transaction
+    //let tx = await getTransaction("0x8bed5c44239cc096f03bd49a6534272ceb9c04c2d595474594f77a3ed4c5beac");
+    //console.log("my tx is:", tx)
+
+    //@ts-ignore
+    //console.log("my tx changes: ", tx.changes[0].data, tx.changes[1].data)
+
+    //let wormholeState = await getWormholeState(accountAddress, accountAddress);
+    //console.log("==========================< Wormhole State >==========================\n", wormholeState);
+}
+
+  if (require.main === module) {
+    main().then((resp) => console.log(resp));
+  }
+
+  //<:!:section_7
+
+

+ 52 - 0
aptos/scripts/setNextSequence.ts

@@ -0,0 +1,52 @@
+import { AptosAccount, TxnBuilderTypes, BCS, HexString, MaybeHexString, AptosClient, FaucetClient, AptosAccountObject } from "aptos";
+import {aptosAccountObject} from "./constants";
+export const NODE_URL = "http://localhost:8080/v1";
+export const FAUCET_URL = "http://localhost:8081";
+
+const client = new AptosClient(NODE_URL);
+
+async function setNextSequence(contractAddress: HexString, accountFrom: AptosAccount): Promise<string> {
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::State`,
+        "setNextSequence",
+        [],
+        [
+        BCS.bcsToBytes(TxnBuilderTypes.AccountAddress.fromHex("0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b")),
+        BCS.bcsSerializeUint64(1), // sequence
+        ]
+      ),
+    );
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000), //max gas to be used
+      BigInt(1), //price per unit gas
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+
+    return transactionRes.hash;
+  }
+
+  async function main(){
+    let accountFrom = AptosAccount.fromAptosAccountObject(aptosAccountObject)
+    let accountAddress = accountFrom.address();//new HexString("277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b");
+    console.log("account address: ", accountAddress);
+    let hash = await setNextSequence(accountAddress, accountFrom);
+    console.log("tx hash: ", hash);
+  }
+
+  if (require.main === module) {
+    main().then((resp) => console.log(resp));
+  }
+
+

+ 205 - 0
aptos/scripts/tests.ts

@@ -0,0 +1,205 @@
+import { AptosAccount, TxnBuilderTypes, BCS, HexString, MaybeHexString, AptosClient, FaucetClient, AptosAccountObject } from "aptos";
+import {aptosAccountObject} from "./constants";
+export const NODE_URL = "http://localhost:8080/v1";
+export const FAUCET_URL = "http://localhost:8081";
+
+//<:!:section_2
+//:!:>section_3
+const client = new AptosClient(NODE_URL);
+
+async function testInitWormholeState(contractAddress: HexString, accountFrom: AptosAccount): Promise<string> {
+  const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+    TxnBuilderTypes.EntryFunction.natural(
+      `${contractAddress.toString()}::Wormhole`,
+      "testInitWormholeState",
+      [],
+      []
+    ),
+  );
+  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+    client.getAccount(accountFrom.address()),
+    client.getChainId(),
+  ]);
+  const rawTxn = new TxnBuilderTypes.RawTransaction(
+    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+    BigInt(sequenceNumber),
+    scriptFunctionPayload,
+    BigInt(1000),
+    BigInt(1),
+    BigInt(Math.floor(Date.now() / 1000) + 10),
+    new TxnBuilderTypes.ChainId(chainId),
+  );
+  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+  const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+  return transactionRes.hash;
+}
+
+async function initWormhole(contractAddress: HexString, accountFrom: AptosAccount): Promise<string> {
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::Wormhole`,
+        "init",
+        [],
+        [
+         BCS.bcsSerializeUint64(101),
+         BCS.bcsSerializeUint64(202), 
+         BCS.bcsSerializeBytes(Buffer.from("0x12323aaa11111aaaaaaa2")),
+        ]
+      ),
+    );
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000),
+      BigInt(1),
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+    
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+    
+    return transactionRes.hash;
+    //return new Promise((resolve, reject)=>resolve("foo"));
+  }
+
+async function testInit(contractAddress: HexString, accountFrom: AptosAccount){
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::Wormhole`,
+        "testInit",
+        [],
+        [],
+      ),
+    );
+    console.log("here1")
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    console.log("here2")
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000),
+      BigInt(1),
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+    console.log(transactionRes);
+    return transactionRes.hash;
+  }
+
+
+  //testSetChainId
+  async function testSetChainId(contractAddress: HexString, accountFrom: AptosAccount){
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::Wormhole`,
+        "testSetChainId",
+        [],
+        [],
+      ),
+    );
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000),
+      BigInt(1),
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+    console.log(transactionRes);
+    return transactionRes.hash;
+  }
+
+  async function testInitMessageHandles(contractAddress: HexString, accountFrom: AptosAccount){
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::Wormhole`,
+        "testInitMessageHandles",
+        [],
+        [],
+      ),
+    );
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000),
+      BigInt(1),
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+    console.log(transactionRes);
+    return transactionRes.hash;
+  }
+
+  async function testDoNothing(contractAddress: HexString, accountFrom: AptosAccount){
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::Wormhole`,
+        "doNothing",
+        [],
+        [],
+      ),
+    );
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000),
+      BigInt(1),
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+    console.log(transactionRes);
+    return transactionRes.hash;
+  }
+  
+  async function main(){
+    let accountFrom = AptosAccount.fromAptosAccountObject(aptosAccountObject)
+    let accountAddress = accountFrom.address();//new HexString("277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b");
+    console.log("account address: ", accountAddress);
+    let hash = await initWormhole(accountAddress, accountFrom);
+    //let hash = await testInit(accountAddress, accountFrom);
+    //let hash = await testSetChainId(accountAddress, accountFrom);
+    //let hash = await testInitMessageHandles(accountAddress, accountFrom);
+    //let hash = await testInitWormholeState(accountAddress, accountFrom);
+    //let hash = await testDoNothing(accountAddress, accountFrom);
+    console.log("tx hash: ", hash);
+  }
+
+  if (require.main === module) {
+    main().then((resp) => console.log(resp));
+  }
+
+  //<:!:section_7
+

+ 27 - 0
aptos/scripts/tsconfig.json

@@ -0,0 +1,27 @@
+{
+    "compilerOptions": {
+      "lib": [
+        "es2021",
+        "dom"
+      ],
+      "types": [
+        "node"
+      ],
+      "module": "commonjs",
+      "target": "es2021",
+      "esModuleInterop": true,
+      "allowSyntheticDefaultImports": true,
+      "moduleResolution": "node",
+      "noImplicitAny": true,
+      "allowJs": true,
+      "preserveConstEnums": true,
+      "sourceMap": true,
+    },
+    "include": [
+      "first_transaction.ts"
+    ],
+    "exclude": [
+      "node_modules",
+      "**/*.spec.ts"
+    ]
+  }

+ 57 - 0
aptos/scripts/upgrade

@@ -0,0 +1,57 @@
+#!/bin/bash
+
+set -eo pipefail
+
+function usage() {
+cat <<EOF >&2
+Usage:
+
+  $(basename "$0") <devnet|testnet> <Core|TokenBridge> -- Perform a contract upgrade
+EOF
+exit 1
+}
+
+NETWORK=$1 || usage
+MODULE=$2 || usage
+
+if [ "$NETWORK" = testnet ]; then
+    # This script upgrades the core bridge in local devnet by generating a
+    # governance VAA and submitting it
+
+    DEPLOYER_ADDR=0x5ad53ef0cb7cd21816a0371c367be38e7874a9d2f71c77af7592f6b0791f6ca3
+    [ -z "$GUARDIAN_SECRET" ] && echo "GUARDIAN_SECRET unset" >&2 && exit 1
+
+elif [ "$NETWORK" = devnet ]; then
+    GUARDIAN_SECRET=cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
+    DEPLOYER_ADDR=0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b
+else
+    usage
+fi
+
+WORMHOLE_ADDR=$(worm contract "$NETWORK" aptos Core)
+TOKEN_BRIDGE_ADDR=$(worm contract "$NETWORK" aptos TokenBridge)
+
+NAMED_ADDRS="wormhole=$WORMHOLE_ADDR,deployer=$DEPLOYER_ADDR,token_bridge=$TOKEN_BRIDGE_ADDR"
+
+case "$MODULE" in
+    Core)
+        DIR="../wormhole"
+    ;;
+    TokenBridge)
+        DIR="../token_bridge"
+    ;;
+    *) echo "unsupported module $MODULE" >&2
+       usage
+       ;;
+esac
+
+HASH=$(worm aptos hash-contracts $DIR --named-addresses "$NAMED_ADDRS")
+VAA=$(worm generate upgrade -c aptos -a "$HASH" -m "$MODULE" -g $GUARDIAN_SECRET)
+
+echo "Submitting VAA: $VAA"
+
+# TODO: --contract-address should not be neded after the sdk has these addresses
+CONTRACT_ADDR=$(worm contract "$NETWORK" aptos "$MODULE")
+worm submit --network "$NETWORK" "$VAA" --contract-address "$CONTRACT_ADDR"
+worm aptos upgrade $DIR --network "$NETWORK" --contract-address "$CONTRACT_ADDR" --named-addresses "$NAMED_ADDRS"
+worm aptos migrate --network "$NETWORK" --contract-address "$CONTRACT_ADDR"

+ 205 - 0
aptos/scripts/write.ts

@@ -0,0 +1,205 @@
+import { AptosAccount, TxnBuilderTypes, BCS, HexString, MaybeHexString, AptosClient, FaucetClient, AptosAccountObject } from "aptos";
+import {aptosAccountObject} from "./constants";
+export const NODE_URL = "http://localhost:8080/v1";
+export const FAUCET_URL = "http://localhost:8081";
+
+//<:!:section_2
+//:!:>section_3
+const client = new AptosClient(NODE_URL);
+
+
+async function testInitWormholeState(contractAddress: HexString, accountFrom: AptosAccount): Promise<string> {
+  const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+    TxnBuilderTypes.EntryFunction.natural(
+      `${contractAddress.toString()}::Wormhole`,
+      "testInitWormholeState",
+      [],
+      []
+    ),
+  );
+  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+    client.getAccount(accountFrom.address()),
+    client.getChainId(),
+  ]);
+  const rawTxn = new TxnBuilderTypes.RawTransaction(
+    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+    BigInt(sequenceNumber),
+    scriptFunctionPayload,
+    BigInt(1000),
+    BigInt(1),
+    BigInt(Math.floor(Date.now() / 1000) + 10),
+    new TxnBuilderTypes.ChainId(chainId),
+  );
+  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+  const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+  return transactionRes.hash;
+}
+
+async function initWormhole(contractAddress: HexString, accountFrom: AptosAccount): Promise<string> {
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::Wormhole`,
+        "init",
+        [],
+        [
+         BCS.bcsSerializeUint64(101),
+         BCS.bcsSerializeUint64(202), 
+         BCS.bcsSerializeBytes(Buffer.from("0x12323aaa11111aaaaaaa2")),
+        ]
+      ),
+    );
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000),
+      BigInt(1),
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+    
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+    
+    return transactionRes.hash;
+    //return new Promise((resolve, reject)=>resolve("foo"));
+  }
+
+async function testInit(contractAddress: HexString, accountFrom: AptosAccount){
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::Wormhole`,
+        "testInit",
+        [],
+        [],
+      ),
+    );
+    console.log("here1")
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    console.log("here2")
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000),
+      BigInt(1),
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+    console.log(transactionRes);
+    return transactionRes.hash;
+  }
+
+
+  //testSetChainId
+  async function testSetChainId(contractAddress: HexString, accountFrom: AptosAccount){
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::Wormhole`,
+        "testSetChainId",
+        [],
+        [],
+      ),
+    );
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000),
+      BigInt(1),
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+    console.log(transactionRes);
+    return transactionRes.hash;
+  }
+
+  async function testInitMessageHandles(contractAddress: HexString, accountFrom: AptosAccount){
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::Wormhole`,
+        "testInitMessageHandles",
+        [],
+        [],
+      ),
+    );
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000),
+      BigInt(1),
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+    console.log(transactionRes);
+    return transactionRes.hash;
+  }
+
+  async function testDoNothing(contractAddress: HexString, accountFrom: AptosAccount){
+    const scriptFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
+      TxnBuilderTypes.EntryFunction.natural(
+        `${contractAddress.toString()}::Wormhole`,
+        "doNothing",
+        [],
+        [],
+      ),
+    );
+    const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
+      client.getAccount(accountFrom.address()),
+      client.getChainId(),
+    ]);
+    const rawTxn = new TxnBuilderTypes.RawTransaction(
+      TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
+      BigInt(sequenceNumber),
+      scriptFunctionPayload,
+      BigInt(1000),
+      BigInt(1),
+      BigInt(Math.floor(Date.now() / 1000) + 10),
+      new TxnBuilderTypes.ChainId(chainId),
+    );
+    const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
+    const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
+    console.log(transactionRes);
+    return transactionRes.hash;
+  }
+  
+  async function main(){
+    let accountFrom = AptosAccount.fromAptosAccountObject(aptosAccountObject)
+    let accountAddress = accountFrom.address();//new HexString("277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b");
+    console.log("account address: ", accountAddress);
+    let hash = await initWormhole(accountAddress, accountFrom);
+    //let hash = await testInit(accountAddress, accountFrom);
+    //let hash = await testSetChainId(accountAddress, accountFrom);
+    //let hash = await testInitMessageHandles(accountAddress, accountFrom);
+    //let hash = await testInitWormholeState(accountAddress, accountFrom);
+    //let hash = await testDoNothing(accountAddress, accountFrom);
+    console.log("tx hash: ", hash);
+  }
+
+  if (require.main === module) {
+    main().then((resp) => console.log(resp));
+  }
+
+  //<:!:section_7

+ 347 - 0
aptos/scripts/yarn.lock

@@ -0,0 +1,347 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@cspotcode/source-map-support@^0.8.0":
+  "integrity" "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="
+  "resolved" "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz"
+  "version" "0.8.1"
+  dependencies:
+    "@jridgewell/trace-mapping" "0.3.9"
+
+"@jridgewell/resolve-uri@^3.0.3":
+  "integrity" "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="
+  "resolved" "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz"
+  "version" "3.1.0"
+
+"@jridgewell/sourcemap-codec@^1.4.10":
+  "integrity" "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
+  "resolved" "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz"
+  "version" "1.4.14"
+
+"@jridgewell/trace-mapping@0.3.9":
+  "integrity" "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="
+  "resolved" "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz"
+  "version" "0.3.9"
+  dependencies:
+    "@jridgewell/resolve-uri" "^3.0.3"
+    "@jridgewell/sourcemap-codec" "^1.4.10"
+
+"@noble/hashes@~1.1.1":
+  "integrity" "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA=="
+  "resolved" "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz"
+  "version" "1.1.2"
+
+"@scure/base@~1.1.0":
+  "integrity" "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA=="
+  "resolved" "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz"
+  "version" "1.1.1"
+
+"@scure/bip39@^1.1.0":
+  "integrity" "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w=="
+  "resolved" "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz"
+  "version" "1.1.0"
+  dependencies:
+    "@noble/hashes" "~1.1.1"
+    "@scure/base" "~1.1.0"
+
+"@tsconfig/node10@^1.0.7":
+  "integrity" "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA=="
+  "resolved" "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz"
+  "version" "1.0.9"
+
+"@tsconfig/node12@^1.0.7":
+  "integrity" "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="
+  "resolved" "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz"
+  "version" "1.0.11"
+
+"@tsconfig/node14@^1.0.0":
+  "integrity" "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="
+  "resolved" "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz"
+  "version" "1.0.3"
+
+"@tsconfig/node16@^1.0.2":
+  "integrity" "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ=="
+  "resolved" "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz"
+  "version" "1.0.3"
+
+"@types/node@*", "@types/node@^18.7.13":
+  "integrity" "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw=="
+  "resolved" "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz"
+  "version" "18.7.13"
+
+"acorn-walk@^8.1.1":
+  "integrity" "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA=="
+  "resolved" "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz"
+  "version" "8.2.0"
+
+"acorn@^8.4.1":
+  "integrity" "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w=="
+  "resolved" "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz"
+  "version" "8.8.0"
+
+"aptos@^1.3.9":
+  "integrity" "sha512-x/h2MEprUu1/gxAvKR7DGqIXT85S2hsXDVXNcstfob0OUtgybnUTf4N7KwjTrQF1XhcmTPcH7Bj7xD6Jb9OWcw=="
+  "resolved" "https://registry.npmjs.org/aptos/-/aptos-1.3.9.tgz"
+  "version" "1.3.9"
+  dependencies:
+    "@scure/bip39" "^1.1.0"
+    "axios" "^0.27.2"
+    "buffer" "^6.0.3"
+    "ed25519-hd-key" "^1.2.0"
+    "js-sha3" "^0.8.0"
+    "tweetnacl" "^1.0.3"
+    "typescript-memoize" "^1.1.0"
+    "yarn" "^1.22.19"
+
+"arg@^4.1.0":
+  "integrity" "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
+  "resolved" "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz"
+  "version" "4.1.3"
+
+"asynckit@^0.4.0":
+  "integrity" "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+  "resolved" "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz"
+  "version" "0.4.0"
+
+"axios@^0.27.2":
+  "integrity" "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ=="
+  "resolved" "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz"
+  "version" "0.27.2"
+  dependencies:
+    "follow-redirects" "^1.14.9"
+    "form-data" "^4.0.0"
+
+"base64-js@^1.3.1":
+  "integrity" "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+  "resolved" "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"
+  "version" "1.5.1"
+
+"buffer@^6.0.3":
+  "integrity" "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="
+  "resolved" "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz"
+  "version" "6.0.3"
+  dependencies:
+    "base64-js" "^1.3.1"
+    "ieee754" "^1.2.1"
+
+"cipher-base@^1.0.1", "cipher-base@^1.0.3":
+  "integrity" "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q=="
+  "resolved" "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz"
+  "version" "1.0.4"
+  dependencies:
+    "inherits" "^2.0.1"
+    "safe-buffer" "^5.0.1"
+
+"combined-stream@^1.0.8":
+  "integrity" "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="
+  "resolved" "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
+  "version" "1.0.8"
+  dependencies:
+    "delayed-stream" "~1.0.0"
+
+"create-hash@^1.1.0":
+  "integrity" "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg=="
+  "resolved" "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz"
+  "version" "1.2.0"
+  dependencies:
+    "cipher-base" "^1.0.1"
+    "inherits" "^2.0.1"
+    "md5.js" "^1.3.4"
+    "ripemd160" "^2.0.1"
+    "sha.js" "^2.4.0"
+
+"create-hmac@1.1.7":
+  "integrity" "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg=="
+  "resolved" "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz"
+  "version" "1.1.7"
+  dependencies:
+    "cipher-base" "^1.0.3"
+    "create-hash" "^1.1.0"
+    "inherits" "^2.0.1"
+    "ripemd160" "^2.0.0"
+    "safe-buffer" "^5.0.1"
+    "sha.js" "^2.4.8"
+
+"create-require@^1.1.0":
+  "integrity" "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
+  "resolved" "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz"
+  "version" "1.1.1"
+
+"delayed-stream@~1.0.0":
+  "integrity" "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+  "resolved" "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
+  "version" "1.0.0"
+
+"diff@^4.0.1":
+  "integrity" "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
+  "resolved" "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz"
+  "version" "4.0.2"
+
+"ed25519-hd-key@^1.2.0":
+  "integrity" "sha512-IWwAyiiuJQhgu3L8NaHb68eJxTu2pgCwxIBdgpLJdKpYZM46+AXePSVTr7fkNKaUOfOL4IrjEUaQvyVRIDP7fg=="
+  "resolved" "https://registry.npmjs.org/ed25519-hd-key/-/ed25519-hd-key-1.3.0.tgz"
+  "version" "1.3.0"
+  dependencies:
+    "create-hmac" "1.1.7"
+    "tweetnacl" "1.0.3"
+
+"follow-redirects@^1.14.9":
+  "integrity" "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
+  "resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz"
+  "version" "1.15.1"
+
+"form-data@^4.0.0":
+  "integrity" "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww=="
+  "resolved" "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz"
+  "version" "4.0.0"
+  dependencies:
+    "asynckit" "^0.4.0"
+    "combined-stream" "^1.0.8"
+    "mime-types" "^2.1.12"
+
+"hash-base@^3.0.0":
+  "integrity" "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA=="
+  "resolved" "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz"
+  "version" "3.1.0"
+  dependencies:
+    "inherits" "^2.0.4"
+    "readable-stream" "^3.6.0"
+    "safe-buffer" "^5.2.0"
+
+"ieee754@^1.2.1":
+  "integrity" "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
+  "resolved" "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz"
+  "version" "1.2.1"
+
+"inherits@^2.0.1", "inherits@^2.0.3", "inherits@^2.0.4":
+  "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+  "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
+  "version" "2.0.4"
+
+"js-sha3@^0.8.0":
+  "integrity" "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
+  "resolved" "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz"
+  "version" "0.8.0"
+
+"make-error@^1.1.1":
+  "integrity" "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
+  "resolved" "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz"
+  "version" "1.3.6"
+
+"md5.js@^1.3.4":
+  "integrity" "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg=="
+  "resolved" "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz"
+  "version" "1.3.5"
+  dependencies:
+    "hash-base" "^3.0.0"
+    "inherits" "^2.0.1"
+    "safe-buffer" "^5.1.2"
+
+"mime-db@1.52.0":
+  "integrity" "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+  "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"
+  "version" "1.52.0"
+
+"mime-types@^2.1.12":
+  "integrity" "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="
+  "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
+  "version" "2.1.35"
+  dependencies:
+    "mime-db" "1.52.0"
+
+"nvm@^0.0.4":
+  "integrity" "sha512-jvmyELykYcdyd0VCGY0E8Aqe5MngEasVvlPvrcJHbwBMUbVqa72mPdQuPzyTcykEtEx7jDrMY0QA5MoV+8EhgA=="
+  "resolved" "https://registry.npmjs.org/nvm/-/nvm-0.0.4.tgz"
+  "version" "0.0.4"
+
+"readable-stream@^3.6.0":
+  "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="
+  "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz"
+  "version" "3.6.0"
+  dependencies:
+    "inherits" "^2.0.3"
+    "string_decoder" "^1.1.1"
+    "util-deprecate" "^1.0.1"
+
+"ripemd160@^2.0.0", "ripemd160@^2.0.1":
+  "integrity" "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA=="
+  "resolved" "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz"
+  "version" "2.0.2"
+  dependencies:
+    "hash-base" "^3.0.0"
+    "inherits" "^2.0.1"
+
+"safe-buffer@^5.0.1", "safe-buffer@^5.1.2", "safe-buffer@^5.2.0", "safe-buffer@~5.2.0":
+  "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+  "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
+  "version" "5.2.1"
+
+"sha.js@^2.4.0", "sha.js@^2.4.8":
+  "integrity" "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ=="
+  "resolved" "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz"
+  "version" "2.4.11"
+  dependencies:
+    "inherits" "^2.0.1"
+    "safe-buffer" "^5.0.1"
+
+"string_decoder@^1.1.1":
+  "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="
+  "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
+  "version" "1.3.0"
+  dependencies:
+    "safe-buffer" "~5.2.0"
+
+"ts-node@^10.9.1":
+  "integrity" "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw=="
+  "resolved" "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz"
+  "version" "10.9.1"
+  dependencies:
+    "@cspotcode/source-map-support" "^0.8.0"
+    "@tsconfig/node10" "^1.0.7"
+    "@tsconfig/node12" "^1.0.7"
+    "@tsconfig/node14" "^1.0.0"
+    "@tsconfig/node16" "^1.0.2"
+    "acorn" "^8.4.1"
+    "acorn-walk" "^8.1.1"
+    "arg" "^4.1.0"
+    "create-require" "^1.1.0"
+    "diff" "^4.0.1"
+    "make-error" "^1.1.1"
+    "v8-compile-cache-lib" "^3.0.1"
+    "yn" "3.1.1"
+
+"tweetnacl@^1.0.3", "tweetnacl@1.0.3":
+  "integrity" "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
+  "resolved" "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz"
+  "version" "1.0.3"
+
+"typescript-memoize@^1.1.0":
+  "integrity" "sha512-LQPKVXK8QrBBkL/zclE6YgSWn0I8ew5m0Lf+XL00IwMhlotqRLlzHV+BRrljVQIc+NohUAuQP7mg4HQwrx5Xbg=="
+  "resolved" "https://registry.npmjs.org/typescript-memoize/-/typescript-memoize-1.1.0.tgz"
+  "version" "1.1.0"
+
+"typescript@^4.7.4", "typescript@>=2.7":
+  "integrity" "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ=="
+  "resolved" "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz"
+  "version" "4.7.4"
+
+"util-deprecate@^1.0.1":
+  "integrity" "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+  "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
+  "version" "1.0.2"
+
+"v8-compile-cache-lib@^3.0.1":
+  "integrity" "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
+  "resolved" "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz"
+  "version" "3.0.1"
+
+"yarn@^1.22.19":
+  "integrity" "sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ=="
+  "resolved" "https://registry.npmjs.org/yarn/-/yarn-1.22.19.tgz"
+  "version" "1.22.19"
+
+"yn@3.1.1":
+  "integrity" "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
+  "resolved" "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz"
+  "version" "3.1.1"

+ 3 - 0
aptos/start_node.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+aptos node run-local-testnet --with-faucet --force-restart

+ 2 - 2
scripts/check-docker-pin.sh

@@ -11,10 +11,10 @@
 #   - We ignore scratch because it's literally the docker base image
 #   - We ignore scratch because it's literally the docker base image
 #   - We ignore solana AS (builder|ci_tests) because it's a relative reference to another FROM call
 #   - We ignore solana AS (builder|ci_tests) because it's a relative reference to another FROM call
 #
 #
-git ls-files | grep "Dockerfile*" | xargs grep -s "FROM" | egrep -v 'sha256|scratch|solana AS (builder|ci_tests)'
+git ls-files | grep "Dockerfile*" | xargs grep -s "FROM" | egrep -v 'sha256|scratch|solana|aptos AS (builder|ci_tests|tests)'
 if [ $? -eq 0 ]; then
 if [ $? -eq 0 ]; then
    echo "[!] Unpinned docker files" >&2
    echo "[!] Unpinned docker files" >&2
    exit 1
    exit 1
 else
 else
    echo "[+] No unpinned docker files"
    echo "[+] No unpinned docker files"
-fi
+fi