> ## Documentation Index
> Fetch the complete documentation index at: https://docs.initia.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrating VIP

This guide explains how a rollup can prepare for and integrate Initia's
[VIP](/home/core-concepts/vip).

## Prerequisites

* [Weave CLI](/developers/developer-guides/tools/clis/weave-cli/rollup/introduction)
* [Minitiad CLI](/developers/developer-guides/tools/clis/minitiad-cli/introduction)

<Steps title="VIP Integration Steps">
  <Step title="Deploy Your Rollup and Install Minitiad CLI">
    First, launch your rollup. For local deployments, you can use the [Weave CLI](/developers/developer-guides/tools/clis/weave-cli/rollup/introduction) to launch a rollup.

    Once your rollup is running, fetch the rollup's version by running the following command:

    ```bash theme={null}
    export RPC_URL={YOUR_ROLLUP_RPC_URL}
    curl -X POST $RPC_URL/abci_info
    ```

    The output will be in the format below. The `version` field is the rollup's version.

    ```json highlight={7} theme={null}
    {
      "jsonrpc": "2.0",
      "id": -1,
      "result": {
        "response": {
          "data": "minitia",
          "version": "v1.0.2",
          "last_block_height": "10458738",
          "last_block_app_hash": "lS/hN6BDFU45Z0Oee04MZm15TS49yx+//SQJsXSSfms="
        }
      }
    }
    ```

    Next, install the `minitiad` CLI that matches the rollup's version.

    <CodeGroup>
      <CodeBlock filename="EVM" language="bash">
        export MINIEVM\_VERSION=1.1.7 # Replace with your rollup's version

        git clone [https://github.com/initia-labs/minievm.git](https://github.com/initia-labs/minievm.git)
        cd minievm
        git checkout \$MINIEVM\_VERSION
        make install
      </CodeBlock>

      <CodeBlock filename="MoveVM" language="bash">
        export MINIMOVE\_VERSION=1.0.6

        git clone [https://github.com/initia-labs/minimove.git](https://github.com/initia-labs/minimove.git)
        cd minimove
        git checkout \$MINIMOVE\_VERSION # Replace with your rollup's version
        make install
      </CodeBlock>

      <CodeBlock filename="WasmVM" language="bash">
        export MINIWASM\_VERSION=1.0.6 # Replace with your rollup's version

        git clone [https://github.com/initia-labs/miniwasm.git](https://github.com/initia-labs/miniwasm.git)
        cd miniwasm
        git checkout \$MINIWASM\_VERSION
        make install
      </CodeBlock>
    </CodeGroup>
  </Step>

  <Step title="Create an operator and VIP contract deployer account">
    Next, create a VIP operator account and a VIP contract deployer account to deploy the VIP scoring contract.

    * The VIP operator account will receive the VIP operator rewards
    * The VIP contract deployer account will handle the deployment of the VIP scoring contract.

    If you have an existing account for these roles, use the `--recover` option to recover it with a BIP39 mnemonic phrase. If you do not have a mnemonic phrase, create a new account without this option.

    ```bash theme={null}
    export OPERATOR_KEY_NAME=operator
    export DEPLOYER_KEY_NAME=deployer

    minitiad keys add $OPERATOR_KEY_NAME --recover
    # > Enter your bip39 mnemonic
    # glare boil shallow hurt distance grant rose pledge begin main stage affair alpha garlic tornado enemy enable swallow unusual foster maid pelican also bus

    minitiad keys add $DEPLOYER_KEY_NAME --recover
    # > Enter your bip39 mnemonic
    # room fruit chalk buyer budget wisdom theme sound north square regular truck deal anxiety wrestle toy flight release actress critic saddle garment just found
    ```

    Alternatively, if you want to use a Ledger hardware wallet, you can use the `--ledger` option to create an account that uses Ledger for signing transactions.

    ```bash theme={null}
    minitiad keys add $OPERATOR_KEY_NAME --ledger
    ```
  </Step>

  <Step title="Deploy the VIP Scoring Contract">
    In this step, you will deploy the VIP scoring contract that tracks addresses and scores. To do so, follow the steps based on your rollup's VM.

    The VIP scoring contract must specify the stage at which the rollup participates in VIP when deployed. To retrieve the current VIP stage, select the example for your network and run the curl request or the TypeScript example. Both query the VIP module store on L1 and return the current stage information.

    <Tabs>
      <Tab title="Mainnet (interwoven-1)">
        ```bash curl theme={null}
        curl https://rest.initia.xyz/initia/move/v1/accounts/0x3a886b32a802582f2e446e74d4a24d1d7ed01adf46d2a8f65c5723887e708789/resources/by_struct_tag?struct_tag=0x3a886b32a802582f2e446e74d4a24d1d7ed01adf46d2a8f65c5723887e708789%3A%3Avip%3A%3AModuleStore
        ```

        ```ts initia.js theme={null}
        import { RESTClient } from '@initia/initia.js'

        const L1_VIP_CONTRACT   = '0x3a886b32a802582f2e446e74d4a24d1d7ed01adf46d2a8f65c5723887e708789'
        const L1_REST_URL       = 'https://rest.initia.xyz'

        async function getCurrentStage(): Promise<string> {
          const rest = new RESTClient(L1_REST_URL)
          return rest.move.resource<any>(L1_VIP_CONTRACT, `${L1_VIP_CONTRACT}::vip::ModuleStore`).then((res) => res.data.stage)
        }
        ```
      </Tab>

      <Tab title="Testnet (initiation-2)">
        ```bash curl theme={null}
        curl https://rest.testnet.initia.xyz/initia/move/v1/accounts/0xe55cc823efb411bed5eed25aca5277229a54c62ab3769005f86cc44bc0c0e5ab/resources/by_struct_tag?struct_tag=0xe55cc823efb411bed5eed25aca5277229a54c62ab3769005f86cc44bc0c0e5ab%3A%3Avip%3A%3AModuleStore
        ```

        ```ts initia.js theme={null}
        import { RESTClient } from '@initia/initia.js'

        const L1_VIP_CONTRACT   = '0xe55cc823efb411bed5eed25aca5277229a54c62ab3769005f86cc44bc0c0e5ab'
        const L1_REST_URL       = 'https://rest.testnet.initia.xyz'

        async function getCurrentStage(): Promise<string> {
          const rest = new RESTClient(L1_REST_URL)
          return rest.move.resource<any>(L1_VIP_CONTRACT, `${L1_VIP_CONTRACT}::vip::ModuleStore`).then((res) => res.data.stage)
        }
        ```
      </Tab>
    </Tabs>

    <Tabs>
      <Tab title="EVM">
        Clone the [`vip-score-evm`](https://github.com/initia-labs/vip-score-evm) repository.

        ```bash theme={null}
        git clone https://github.com/initia-labs/vip-score-evm.git
        ```

        Compile the `VIPScore.sol` contract. If you do not have [Foundry](https://github.com/foundry-rs/foundry) installed, follow the [Foundry installation instructions](https://getfoundry.sh).

        ```bash theme={null}
        forge build
        ```

        Deploy the contract. Before running the script, set these environment variables:

        * `JSON_RPC_URL`: your rollup's RPC endpoint
        * `PRIVATE_KEY`: the VIP contract deployer key
        * `INIT_STAGE`: the starting VIP stage number

        To get `INIT_STAGE`, you can check the current VIP stage by using the curl request or the TypeScript example provided in the previous note.

        ```bash theme={null}
        export JSON_RPC_URL=https://jsonrpc-evm-1.anvil.asia-southeast.initia.xyz  # Replace with your rollup's JSON_RPC endpoint
        export PRIVATE_KEY=0xabcd1234...                                           # Replace with your deployer's private key
        export INIT_STAGE=1                                                        # Replace with the starting stage number for scoring.

        forge script script/VipScore.s.sol:DeployVipScore --rpc-url $JSON_RPC_URL --broadcast

        # ...
        # ✅  [Success] Hash: 0xd55beed5a745b203b56dc68c9e9141fcfd433c4c47587ce50655a99f5c449abc
        # Contract Address: 0x1F00dfc319F1B74462B2Ef301c3978ee71f0d0E2
        # Block: 238
        # Paid: 0.000000000000525763 ETH (525763 gas * 0.000000001 gwei)

        # ✅ Sequence #1 on 1982194020580198 | Total Paid: 0.000000000000525763 ETH (525763 gas * avg 0.000000001 gwei)
        # ...
        ```
      </Tab>

      <Tab title="MoveVM">
        Clone the [`vip-score-move`](https://github.com/initia-labs/vip-score-move) repository.

        ```bash theme={null}
        git clone https://github.com/initia-labs/vip-score-move.git
        ```

        Set the `vip_score.move` deployer address in the `Move.toml` file. You will use this address to deploy and interact with the contract.

        ```toml theme={null}
        [addresses]
        vip_score = "0x1234..." # Replace with your deployer address
        ```

        Compile the Move package.

        ```bash theme={null}
        cd vip-score-move
        minitiad move build
        ```

        Deploy the contract. Make sure to set the `GAS_PRICES`, `RPC_NODE_URL`, and `CHAIN_ID` environment variables before running the command.

        ```bash theme={null}
        export GAS_PRICES=0.015l2/07b129ceb9c4b0bdef7db171ce1e22f90d34bc930058b23e21adf8cc938d8145 # Replace with your rollup gas prices
        export RPC_NODE_URL=https://rpc-move-1.anvil.asia-southeast.initia.xyz                     # Replace with your rollup's RPC endpoint
        export CHAIN_ID=move-1                                                                     # Replace with your rollup's chain ID

        minitiad move deploy \
          --from $DEPLOYER_KEY_NAME \
          --gas auto \
          --gas-prices $GAS_PRICES \
          --node $RPC_NODE_URL \
          --chain-id $CHAIN_ID
        ```
      </Tab>

      <Tab title="WasmVM">
        Clone the [`vip-score-wasm`](https://github.com/initia-labs/vip-score-wasm) repository.

        ```bash theme={null}
        git clone https://github.com/initia-labs/vip-score-wasm.git
        ```

        Compile the Wasm package. If you don't have [Rust](https://www.rust-lang.org/), follow the [Rust and Cargo installation instructions](https://doc.rust-lang.org/cargo/getting-started/installation.html).

        ```bash theme={null}
        cd vip-score-wasm
        cargo build --release --target wasm32-unknown-unknown
        ```

        Upload the contract. Make sure to set the `GAS_PRICES`, `RPC_NODE_URL`, and `CHAIN_ID` environment variables before running the command.

        ```bash theme={null}
        export GAS_PRICES=0.015l2/8b3e1fc559b327a35335e3f26ff657eaee5ff8486ccd3c1bc59007a93cf23156 # Replace with your rollup gas prices
        export RPC_NODE_URL=https://rpc-wasm-1.anvil.asia-southeast.initia.xyz                     # Replace with your rollup's RPC endpoint
        export CHAIN_ID=wasm-1                                                                     # Replace with your rollup's chain ID

        minitiad tx wasm store ./target/wasm32-unknown-unknown/release/vip_score.wasm \
          --from $DEPLOYER_KEY_NAME \
          --gas auto \
          --gas-prices $GAS_PRICES \
          --node $RPC_NODE_URL \
          --chain-id $CHAIN_ID
        ```

        To instantiate the contract, you need to fetch the code ID from the transaction output. You'll need [`jq`](https://jqlang.org/download/) to parse the JSON output.

        ```bash theme={null}
        TX_HASH=4CDCE81C5D0FFBCB92683E64198B4DA9F449707BB4F87FCFD8E3F02EBCE042CF
        RESP=$(minitiad q tx $TX_HASH -o json --node $RPC_NODE_URL)
        echo "$RESP" | jq -r '.events[]| select(.type=="store_code").attributes[]| select(.key=="code_id").value'
        ```

        The output is the code ID of the uploaded contract, which you will use to instantiate it. To get `INIT_STAGE`, check the current VIP stage using the curl request or TypeScript example from the previous note.

        ```bash theme={null}
        export ADDRESS=$(minitiad keys show $KEY_NAME -a)
        export CODE_ID=100         # Replace with the actual code ID from the previous step
        export INIT_STAGE=1        # Set the initial stage number
        export LABEL="vip_score"   # Set the label for the contract
        export INIT_MSG='{"allow_list":["'"$ADDRESS"'"],"init_stage":'"$INIT_STAGE"'}'

        minitiad tx wasm instantiate "$CODE_ID" "$INIT_MSG" \
          --admin $ADDRESS \
          --from $KEY_NAME \
          --label $LABEL \
          --gas auto \
          --gas-prices $GAS_PRICES \
          --node $RPC_NODE_URL \
          --chain-id $CHAIN_ID
        ```
      </Tab>
    </Tabs>

    Save the deployed contract address. You will need it for the VIP whitelist proposal.
  </Step>

  <Step title="Register the Rollup in the Initia Registry">
    Clone the Initia Registry repository.

    ```bash theme={null}
    git clone https://github.com/initia-labs/initia-registry.git
    ```

    Then, add your rollup information to the registry repo before submitting a pull request. For detailed instructions, see the [Initia Registry page](/developers/developer-guides/integrating-initia-apps/registry/introduction).
  </Step>

  <Step title="Whitelist VIP Proposal">
    Draft a forum post with the whitelist template. Include your operator address, scoring policy, and VIP score contract address. See the [Whitelisting Rollup for VIP](/developers/developer-guides/integrating-initia-apps/vip/whitelist-rollup-for-vip) guide for the full procedure. This proposal is required only for mainnet rollups. For testnet deployments, contact the Initia team directly.
  </Step>

  <Step title="Operate the VIP Scoring Contract">
    Each VIP stage follows the same sequence of steps. Use the methods below to update scores and finalize each stage.

    <Tabs>
      <Tab title="EVM">
        | Action         | Method                                    | Description                                                                                       |
        | -------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------- |
        | Update scores  | `updateScores(stage, addrs[], amounts[])` | Update the scores for a list of addresses in the specified stage                                  |
        | Finalize stage | `finalizeStage(uint64 stage)`             | Finalize the given stage, preventing further changes and prepares the contract for the next stage |

        This code snippet shows how to use the [viem](https://viem.sh/) library to interact with the VIP scoring contract:

        ```ts vip-score-evm-tutorial.ts theme={null}
        import { createPublicClient, createWalletClient, http, parseAbi, encodeFunctionData, Hash, defineChain } from 'viem';
        import { privateKeyToAccount } from 'viem/accounts';
        import { RESTClient } from '@initia/initia.js';

        /* -------------------------------------------------------- *
         *  Environment variables                                   *
         * -------------------------------------------------------- */

        const JSON_RPC_URL     =  process.env.JSON_RPC_URL   || 'https://jsonrpc-evm-1.anvil.asia-southeast.initia.xyz'; // Your rollup's JSON RPC endpoint
        const PRIVATE_KEY      =  process.env.PRIVATE_KEY    || '0xabcd1234...';                                         // Your contract deployer's private key. Do not hardcode it in production
        const SCORE_CONTRACT   =  process.env.SCORE_CONTRACT || '0x12345...';                                            // The deployed VIP scoring contract address
        const EVM_CHAIN_ID     =  process.env.EVM_CHAIN_ID   || '1982194020580198';                                      // Your rollup's chain ID
        const TARGET_STAGE     =  process.env.TARGET_STAGE   || '1';                                                     // The stage number you want to update scores for

        /* -------------------------------------------------------- *
         *  Update addresses and scores (Mock Implementation)       *
         *  Replace these with actual addresses and scores          *
         * -------------------------------------------------------- */

        // ADDRESSES and SCORES should be arrays of the same length.
        const ADDRESSES = [
          '0x1111111111111111111111111111111111111111',
          '0x2222222222222222222222222222222222222222',
        ] as `0x${string}`[];
        const SCORES = [100n, 250n];

        const chain = defineChain({
          id: parseInt(EVM_CHAIN_ID),
          name: 'MiniEVM',
          nativeCurrency: {
            decimals: 18,
            name: 'Gas Token',
            symbol: 'GAS',
          },
          rpcUrls: {
            default: {
              http: [JSON_RPC_URL],
            },
          },
        })

        const publicClient  = createPublicClient({ chain, transport: http(JSON_RPC_URL) });
        const account       = privateKeyToAccount(PRIVATE_KEY as `0x${string}`);
        const walletClient  = createWalletClient({ chain, transport: http(JSON_RPC_URL), account });

        const vipAbi = parseAbi([
          'function updateScores(uint64 stage, address[] addrs, uint64[] amounts)',
          'function finalizeStage(uint64 stage)',
        ]);

        async function send(txData: Hash) {
          const receipt = await publicClient.waitForTransactionReceipt({ hash: txData });
          if (receipt.status !== 'success') throw new Error(`Tx failed: ${txData}`);
          return receipt;
        }

        async function run() {
          const stage = TARGET_STAGE; // or await getCurrentStage();

          /* update scores ---------------------------------- */
          const tx1 = await walletClient.sendTransaction({
            to: SCORE_CONTRACT as `0x${string}`,
            data: encodeFunctionData({
              abi: vipAbi,
              functionName: 'updateScores',
              args: [BigInt(stage), ADDRESSES, SCORES],
            }),
          });
          await send(tx1);
          console.log('Scores updated successfully.');

          /* finalize stage --------------------------------- */
          const tx2 = await walletClient.sendTransaction({
            to: SCORE_CONTRACT as `0x${string}`,
            data: encodeFunctionData({ abi: vipAbi, functionName: 'finalizeStage', args: [BigInt(stage)] }),
          });
          await send(tx2);
          console.log('Stage finalized successfully.');
        }

        run().catch(console.error);
        ```

        <Note>
          To get the EVM chain ID, call the `eth_chainId` JSON-RPC method. For example, using `curl`:

          ```bash theme={null}
          curl -X POST https://jsonrpc-evm-1.anvil.asia-southeast.initia.xyz/ \
            -H "Content-Type: application/json" \
            -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
          ```
        </Note>
      </Tab>

      <Tab title="MoveVM">
        | Action         | Method                                                   | Description                                                                                                                                                       |
        | -------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
        | Add deployer   | `add_deployer_script(signer, stage)`                     | Add the deployer to the VIP scoring contract for the specified stage. This ensures that the deployer has the necessary permissions to interact with the contract. |
        | Set init stage | `set_init_stage(signer, stage)`                          | Set the initial stage for the VIP process                                                                                                                         |
        | Update scores  | `update_score_script(signer, stage, addrs[], amounts[])` | Update the scores for a list of addresses in the specified stage                                                                                                  |
        | Finalize stage | `finalize_script(signer, stage)`                         | Finalize the given stage, preventing further changes and prepares the contract for the next stage                                                                 |

        ```ts vip-score-move-tutorial.ts theme={null}
        import { bcs, isTxError, MnemonicKey, Msg, MsgExecute, RESTClient, Wallet } from '@initia/initia.js'

        /* -------------------------------------------------------- *
         *  Environment variables                                   *
         * -------------------------------------------------------- */

        const REST_URL       = process.env.REST_URL       || 'https://rest-move-1.anvil.asia-southeast.initia.xyz';  // Your rollup's REST endpoint
        const MNEMONIC_KEY   = process.env.MNEMONIC_KEY   || 'castle lung ...';                                      // Your contract deployer's mnemonic key. Do not hardcode it in production
        const SCORE_CONTRACT = process.env.SCORE_CONTRACT || '0x12345...';                                           // The deployed VIP scoring contract address
        const TARGET_STAGE   = process.env.TARGET_STAGE   || '1';                                                    // The stage number you want to update scores for

        /* -------------------------------------------------------- *
         *  Update addresses and scores (Mock Implementation)       *
         *  Replace these with actual addresses and scores          *
         * -------------------------------------------------------- */

        // ADDRESSES and SCORES should be arrays of the same length.
        const ADDRESSES = [
          '0x1111111111111111111111111111111111111111',
          '0x2222222222222222222222222222222222222222'
        ] as `0x${string}`[]
        const SCORES = [100n, 250n]

        const restClient = new RESTClient(REST_URL)
        const wallet = new Wallet(
          restClient,
          new MnemonicKey({
            mnemonic: MNEMONIC_KEY
          })
        )

        async function send(msgs: Msg[]) {
          const tx = await wallet.createAndSignTx({
            msgs
          })

          const broadcastRes = await wallet.rest.tx.broadcast(tx)
          if (isTxError(broadcastRes)) {
            throw new Error(`Error while sending tx: ${broadcastRes.code} ${broadcastRes.raw_log}`)
          }
        }

        async function run() {
          const stage = TARGET_STAGE // or await getCurrentStage();

          /* add deployer ------------------------------ */
          const msgs0 = [
            new MsgExecute(
              wallet.key.accAddress,
              SCORE_CONTRACT,
              'vip_score',
              'add_deployer_script',
              [],
              [
                bcs.address().serialize(wallet.key.accAddress).toBase64()
              ]
            )
          ]
          await send(msgs0)
          console.log('Deployer added successfully.')

          /* set initial stage ---------------------------- */
          const msgs1 = [
            new MsgExecute(
              wallet.key.accAddress,
              SCORE_CONTRACT,
              'vip_score',
              'set_init_stage',
              [],
              [
                bcs.u64().serialize(TARGET_STAGE).toBase64()
              ]
            )
          ]
          await send(msgs1)
          console.log('Initial stage set successfully.')

          /* update scores --------------------------------- */
          const msgs2 = [
            new MsgExecute(
              wallet.key.accAddress,
              SCORE_CONTRACT,
              'vip_score',
              'update_score_script',
              [],
              [
                bcs.u64().serialize(stage).toBase64(),
                bcs.vector(bcs.address()).serialize(ADDRESSES).toBase64(),
                bcs.vector(bcs.u64()).serialize(SCORES).toBase64()
              ]
            )
          ]
          await send(msgs2)
          console.log('Scores updated successfully.')

          /* finalize stage --------------------------------- */
          const msgs3 = [
            new MsgExecute(
              wallet.key.accAddress,
              SCORE_CONTRACT,
              'vip_score',
              'finalize_script',
              [],
              [
                bcs.u64().serialize(stage).toBase64()
              ]
            )
          ]
          await send(msgs3)
          console.log('Stage finalized successfully.')
        }

        run().catch(console.error)

        ```
      </Tab>

      <Tab title="WasmVM">
        | Action         | Method                                             | Description                                                                                       |
        | -------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
        | Update scores  | `update_scores(signer, stage, addrs[], amounts[])` | Update the scores for a list of addresses in the specified stage                                  |
        | Finalize stage | `finalize_stage(stage)`                            | Finalize the given stage, preventing further changes and prepares the contract for the next stage |

        ```ts vip-score-wasm-tutorial.ts theme={null}
        import { Coins, isTxError, MnemonicKey, Msg, MsgExecuteContract, RESTClient, Wallet } from '@initia/initia.js'

        /* -------------------------------------------------------- *
         *  Environment variables                                   *
         * -------------------------------------------------------- */

        const RPC_URL        = process.env.REST_URL       || 'https://rest-wasm-1.anvil.asia-southeast.initia.xyz';  // Your rollup's REST endpoint
        const MNEMONIC_KEY   = process.env.MNEMONIC_KEY   || 'castle ping ...';                                      // Your contract deployer's mnemonic key. Do not hardcode it in production
        const SCORE_CONTRACT = process.env.SCORE_CONTRACT || 'init1ga1g...';                                         // The deployed VIP scoring contract address
        const TARGET_STAGE   = process.env.TARGET_STAGE   || '1';                                                    // The stage number you want to update scores for

        /* -------------------------------------------------------- *
         *  Update addresses and scores (Mock Implementation)       *
         *  Replace these with actual addresses and scores          *
         * -------------------------------------------------------- */

        // ADDRESSES and SCORES should be arrays of the same length.
        const ADDRESSES = [
          'init1lf0swvvhy3vqautdemmvunfmp0grfrjgzznx9s',
          'init1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqr5e3d'
        ]
        const SCORES = [100, 250]

        const restClient = new RESTClient(RPC_URL)
        const wallet = new Wallet(
          restClient,
          new MnemonicKey({
            mnemonic: MNEMONIC_KEY
          })
        )

        async function send(msgs: Msg[]) {
          const tx = await wallet.createAndSignTx({
            msgs
          })

          const broadcastRes = await wallet.rest.tx.broadcast(tx)
          if (isTxError(broadcastRes)) {
            throw new Error(`Error while sending tx: ${broadcastRes.code} ${broadcastRes.raw_log}`)
          }
        }

        async function run() {
          const stage = Number(TARGET_STAGE) // or await getCurrentStage();

          /* update scores ----------------------------- */
          const msgs1 = [
            new MsgExecuteContract(
              wallet.key.accAddress,
              SCORE_CONTRACT,
              Buffer.from(
                JSON.stringify({
                  update_scores: {
                    stage,
                    scores: [
                      ...ADDRESSES.map((addr, i) => ([addr, SCORES[i]]))
                    ]
                  }
                })
              ).toString('base64'),
              new Coins()
            )
          ]
          await send(msgs1)
          console.log('Scores updated successfully.')

          /* finalize stage --------------------------------- */
          const msgs2 = [
            new MsgExecuteContract(
              wallet.key.accAddress,
              SCORE_CONTRACT,
              Buffer.from(
                JSON.stringify({
                  finalize_stage: {
                    stage,
                  },
                })
              ).toString('base64'),
              new Coins()
            )
          ]
          await send(msgs2)
          console.log('Stage finalized successfully.')
        }

        run().catch(console.error)
        ```
      </Tab>
    </Tabs>
  </Step>
</Steps>
