Live Example

Let’s use this live example JSON to illustrate how to create, enter, and complete a match:

{
  "winOracle": null,
  "matchState": { "initialized": true },
  "winOracleCooldown": 10,
  "space": 300,
  "minimumAllowedEntryTime": null,
  "tokenEntryValidation": [
    {
      "filter": {
        "parent": {
          "key": "2aEHhUyRXvV18i7wb17nNJsD2qafHpiJcKS3wcBgUoui"
        }
      },
      "isBlacklist": false,
      "validation": {
        "key": "nameAxQRRBnd4kLfsVoZBBXfrByZdZTkh8mULLxLyqV",
        "code": 1
      }
    }
  ],
  "authority": null,
  "leaveAllowed": true,
  "joinAllowedDuringStart": true,
  "oracleState": {
    "seed": "Gz5x6myaWWSKKzAhh2LHA5YmXExLiyTfj89S9zXyT17g",
    "authority": "44kiGWWsSgdqPMvmqYgTS78Mx2BKCWzduATkfY4biU97",
    "finalized": false,
    "tokenTransferRoot": null,
    "tokenTransfers": [
    
    ]
  },
  "tokensToJoin": [
    {
      "mint": "AoDxuMeVojMb9pBjcrKnCrz6e2u6HxdcJBPgUDDfd4W7",
      "amount": 1,
      "sourceType": 1,
      "index": 1,
      "validationProgram": "nameAxQRRBnd4kLfsVoZBBXfrByZdZTkh8mULLxLyqV"
    },
    {
      "mint": "9UtumWmQhYFxS5EnqxccFm1t7JixT5kivLiYASA4AiaG",
      "amount": 1,
      "sourceType": 2,
      "index": null
    }
  ]
}

This JSON actually is setup to do a few different things, at different points among the lifetime of the match. We’ll go over each as we do it. First, let’s create the oracle!

This uses the “oracleState” hash to seed and create an oracle. Whatever is in this hash file will be placed in the oracle every time the above command is run. Alternatively, if oracleState is null and winOracle is set, the expectation is that the oracle is not owned by the Matches program and you’re choosing not to use this endpoint to update it, but it still fits the standard.

Now let’s create the match:

Checking the token entry validation in our JSON, or via the show match call, run here, we can see that only one type of token can be added:

We happen to know that the first entry in the tokensToJoin list is the token whose parent matches, see:

We can also see that when this token is added, it will do a CPI call to a specific validation we set. This is entirely optional - removing the callback from the JSON would remove this requirement. It just allows the match author to add additional custom logic beyond the standard filters.

To add this token to the match, we run:

This command uses the “tokensToJoin” array in the JSON file and either iterates through and adds each token to the match escrow OR if -i is provided, only adds that index (as we are doing here). If we then try to add index 1, we will see it fail due to our token entry validation.

After this, we can change the entry for matchState to started in the JSON, then issue the update using the update command.

At this point, now we must use the oracle to determine the outcome of the match. Let’s update the Oracle hash to the following:

Please note that this JSON/update call combo will only work if your oracle is an internally produced one. If it is external, the external party must do their own writing. To issue this oracle state to the on-chain oracle, run

Now that the oracle has been updated, you’ll need to notify the match that the oracle has changed and it should “listen” to it. This will move the match from the Started state to the Finalized state.

Note that this call is permissionless! Anybody can do this. Now if we run show_match, we’ll see that the state has changed. Now it is up to permissionless cranks to follow the TokenTransfers provided and issue out the tokens to either original owners or new owners.

In this case, this will issue a single command to the cluster to move the token to its new owner. Now the match will have entered its final state, PaidOut, because all tokens have left the match escrow. Let’s drain the match and oracle and reclaim lamports!

Last updated