# Welcome!

## Welcome to the Metapass API

This guide is for developers wanting to integrate the Metapass NFTs into their online platforms, such as for gated online entry. For live events, you can simply use the scanner tool within the Metapass frontend.

Read on to find out how Metapass can play a part of your platform, whether it is for ticket sales, authentication and more.

## Starting from scratch?

Read our quick start guide to start issuing requests to our graph node or smart contracts. A good understanding of Web3 and Javascript is recommended.

{% content-ref url="/pages/npteqHC8MSDd75uULQ3T" %}
[Quick Start](/quick-start)
{% endcontent-ref %}

{% content-ref url="/pages/lUWZ1rwARvi7H7H9GeYO" %}
[Graph Node Requests](/quick-start/graph-node-requests)
{% endcontent-ref %}

{% content-ref url="/pages/lK1FzUr0YlySN2HCt4L3" %}
[Smart Contract Requests](/quick-start/smart-contract-requests)
{% endcontent-ref %}

## Want to deep dive?

Dive a little deeper and start exploring our API reference to get an idea of everything that's possible with the API:

{% content-ref url="/pages/JaTWVws8jEw5tif08OS9" %}
[Graph Node API](/reference/graph-node-api)
{% endcontent-ref %}

{% content-ref url="/pages/hOsL9ID8bzznJAhfpjns" %}
[Smart Contract Specifications](/reference/smart-contract-specifications)
{% endcontent-ref %}


# Quick Start

## Figure out which service you need

Our Graph node indexer is free for anyone to query, and is simpler to query with less technical details. However, for some users, it may be more suitable to query our smart contracts directly.

We would recommend interacting with our smart contracts if you:

* Only require checking ownership of a ticket NFT for access, without needing to know which exact NFT token ID the user owns. This is commonly the case for websites that simply wish to use Metapass tickets for authentication
* Require some advanced interaction with the smart contracts directly. For example, needing to approve or transfer ticket NFTs on your platform.

For most users, we recommend using our graph node service if you:

* Need to know which exact NFTs a user owns. This is the often case if you need to obtain additional information about each ticket. i.e, if you need to maintain additional data regarding each ticket owned.
* Need to know the transaction history of a particular ticket NFT. This is useful for building 3rd party marketplaces on top of our NFTs.
* Do not need to interact directly (a.k.a. write to) our smart contracts, you just need to read information about them

## Integrate Metamask

For both services, you will need a way to connect your user with his Metamask wallet. It is recommended to do so with a modern javascript frontend stack, such as using React or Angular. See below for two guides on how to do so on the Theta blockchain:

{% embed url="<https://github.com/thetatoken/useDApp>" %}
useDApp Library
{% endembed %}

{% embed url="<https://github.com/thetatoken/theta-metamask-demo>" %}
A demo Metamask project, built to mimic the Uniswap interface&#x20;
{% endembed %}

## Getting your smart contract address

Next, you need to know what the smart contract address(es) is for the tickets you have created on Metapass. For individual events, follow the steps below to do so:

1. Navigate to [beta.metapass.world](https://beta.metapass.world/events/)
2. Click on the events tab on the top of the page
3. Find and click on the event you want to use your smart contracts for
4. Click on the "Creator Dashboard" on the top right of the page
5. Click on the "Balances" subpage on the left sidebar
6. Here, you can see a list of tickets you have created for this event. Take note of their smart contract addresses.

## Next steps

After you have a Metamask connection setup, follow through our next pages to see how you can integrate Metapass NFTs:


# Graph Node Requests

## Prerequisites

For this section, you will need:

* A user's Theta Network wallet address, see the previous page on how to obtain this
* A HTTP request library installed, such as [axios](https://www.npmjs.com/package/axios)
* The smart contract address(es) of your event

## Querying the GraphQL backend

We have a [GraphQL playground](https://graphql.tkets.io/subgraphs/name/tkets-core/graphql) for you to send requests directly before integrating this into your platform.

To start, try sending the following request using the playground:

```graphql
query {
  ticketTokens (where: {
      owner: "0x059377c014cfc12dd2612ebfe9cfd1a6fc1a8883", 
      ticket_in: [
        "0x0478578c5e906afeb1bdbbf358929affbf1575c8",
        "0xaa7fc9c591eab1f80e7e29a1f88ee144c6a3694f"
       ]
     }) 
  {
    owner { id },
    tokenID
  
}
```

The above request searches all of our ticket tokens where the owner address is `0x059377c014cfc12dd2612ebfe9cfd1a6fc1a8883` and the ticket smart contract address is either `0x0478578c5e906afeb1bdbbf358929affbf1575c8` or `0xaa7fc9c591eab1f80e7e29a1f88ee144c6a3694f`.

## Searching for past transactions

Let's try something more advanced now, and try to find all of the past transactions of a ticket. Try sending the following request to the playground:

```graphql
query {
  transfers (where: {ticketToken: "0x0478578c5e906afeb1bdbbf358929affbf1575c8#65"}) {
    from,
    to,
    ticketToken {
      tokenID,
      ticket {
        id
      },
      owner {
        id
      }
    }
  }
}
```

This searches the database for all transfers that had taken place for the ticket with smart contract address `0x0478578c5e906afeb1bdbbf358929affbf1575c8` and token ID `65`. It returns the address from which it was transferred, the address it was transferred to, as well as the current owner and token ID of the ticket.

## Querying Metapass platform data

Next, let's try the following query:

```graphql
query {
  tketsdayDatas (where: {date_gt: 1635752657}, orderBy: date, orderDirection: desc, first: 10) {
    date,
    dailyTxns,
    dailyVolumeTFUEL,
    totalVolumeTFUEL,
    eventCount
  }
}
```

This query checks the daily data collated about the platform, and finds the first 10 entries corresponding to a date greater than a timestamp of `1635752657`, ordered by descending date. It returns the date of the entry, the number of daily transactions, the total and daily volume of TFUEL transacted, as well as the event count.

By now, you should have a basic understanding of how the query system works, and can construct your own queries to suit the information you need. You can refer to the Graph Node API guide for a full schema of the data indexed by the Graph node, or also read more in the [GraphQL API docs](https://thegraph.com/docs/en/developer/graphql-api/) for more information about the query system.

## Querying by HTTP request

Now, with your query crafted, you can query the database programmatically using a HTTP POST request rather than doing it manually in the playground. This also allows you to set any variables within your query.

## Query the GraphQL database

<mark style="color:green;">`POST`</mark> `https://graphql.tkets.io/subgraphs/name/tkets-core/graphql/`

Submits a query to the GraphQL database with the specified variables, and returns a JSON response with the result objects

#### Request Body

| Name                                    | Type   | Description                                               |
| --------------------------------------- | ------ | --------------------------------------------------------- |
| query<mark style="color:red;">\*</mark> | String | Your query (as above), in a plaintext string              |
| variables                               | JSON   | (Optional) Variables within the query that can be defined |

{% tabs %}
{% tab title="200: OK JSON response with objects specifieid by the query" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

Make sure to use a POST method to submit the request. Mutations are not allowed because of restrictions on the graph node, and therefore the database is read only.

{% hint style="info" %}

#### Securing your backend endpoints

For protected endpoints that require only users who are authenticated (for example, an endpoint that allows users who hold NFTs to change their name on your platform or make a vote), you will need to check on both your frontend and backend if they are indeed holders of your NFT.&#x20;

This can be done with the GraphQL queries on this page, as well as a signature verification on your backend. See [signature verification](/quick-start/miscellaneous#signature-verification) for more details
{% endhint %}

For example, you may use the following code to submit a request:

{% tabs %}
{% tab title="React TSX" %}

```tsx
import axios from 'axios'

const GRAPHQL_ADDRESS = 'https://graphql.tkets.io'
const GRAPHQL_LIMIT = 100

// This query finds the smart contract addresses of tickets
// that an account owns
const QUERY_OWNED_TICKETS_OF_ACCOUNT = `
  query ($ownerAddress: ID!, $skipNumber: Int!) {
    ticketTokens (where: {owner: $ownerAddress}, skip: $skipNumber) {
      ticket {
        id
      }
    }
  }
`

// Main function to call
export function getOwnedTicketsOfAccount(account: string) {
  return tryGetOwnedTicketsOfAccountWithSkip(account, 0, [])
}

// Helper function, can be called recursively with an accumulator
export async function tryGetOwnedTicketsOfAccountWithSkip(address: string, skip: number, accumulator: any[]) : Promise<string[]> {
  return axios.post(`${GRAPHQL_ADDRESS}/subgraphs/name/tkets-core`, 
    { 
      query: QUERY_OWNED_TICKETS_OF_ACCOUNT, 
      variables: {
        ownerAddress: address.toLowerCase(),
        skipNumber: skip
      }
    }
  ).then((r) => {
    if (r.status === 200) {
      // convert JSON result into a list of ticket smart contract address strings
      const ticketsParsed = r.data.data.ticketTokens.map((ticketToken: any) => {
        return ticketToken.ticket.id as string
      })

      // add result to the accumulator
      accumulator = accumulator.concat(ticketsParsed)

      // check if we have reached the GraphQL query limit of 100
      // if so, we need to submit another request with the skip variable
      // to get the next 100 ticket smart contract addresses
      if (r.data.data.ticketTokens.length === GRAPHQL_LIMIT) {
        return tryGetOwnedTicketsOfAccountWithSkip(address, skip + GRAPHQL_LIMIT, accumulator)
      }

      // Convert to set in order to remove any duplicates
      const ticketParsedSet = Array.from(new Set(accumulator))
      
      return ticketParsedSet as string[]
    }

    return [] as string[]
  }).catch((e: Error) => {
    return [] as string[]
  })
}
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

GRAPHQL_ADDRESS = 'https://graphql.tkets.io'
GRAPHQL_LIMIT = 100

QUERY_TICKET_HOLDER = '''
  query ($ownerAddress: ID!, $skipNumber: Int!) {
    ticketTokens (where: {owner: $ownerAddress}, skip: $skipNumber) {
      ticket {
        id
      }
    }
  }
'''

def get_owned_tickets_of_account(address, skip=0, accumulator=None):
    accumulator = accumulator or []
    ticket_set = []
    
    try:
        holder_response = requests.post(f"{GRAPHQL_ADDRESS}/subgraphs/name/tkets-core", json={
            "query": QUERY_TICKET_HOLDER,
            "variables": {
                "ownerAddress": address.lower(),
                "skipNumber": skip
            }
        })
        
        for ticket_json in holder_response["data"]["ticketTokens"]:
          accumulator.append(ticket_json["ticket"]["id"])
        
        if (len(holder_response["data"]["ticketTokens"]) === GRAPHQL_LIMIT) {
          return get_owned_tickets_of_account(address, skip + GRAPHQL_LIMIT, accumulator)
        }
        
        ticket_set = list(set(accumulator))
    except:
        # error retrieving GraphQL, try again later
        raise
        
    return ticket_set
```

{% endtab %}
{% endtabs %}


# Smart Contract Requests

## Prerequisites

For this section, you will need:

* A user's Theta Network wallet address, see the previous page on how to obtain this
* A web3 library installed, such as [ethers.js](https://www.npmjs.com/package/ethers), and connected to the Theta Mainnet RPC endpoint
* [web3-react](https://www.npmjs.com/package/web3-react)
* The smart contract address(es) of your event

## Checking ownership of a ticket

{% tabs %}
{% tab title="React TSX" %}

```tsx
import { useWeb3React } from '@web3-react/core'

const { library } = useWeb3React()

async function getTicketContractBalance(ticketAddress: string, library: any) {
  return library.getBalance(ticketAddress)
}
```

{% endtab %}
{% endtabs %}

## Stamping a ticket

This requires a smart contract interaction, and therefore will cost gas. You will need to [obtain an intstance of ticket contract](/quick-start/miscellaneous#getting-a-smart-contract-instance-with-ethers) first.

```tsx
import { BigNumber, ethers } from 'ethers'

const { library, account } = useWeb3React()

const ticketAddress = "..."
const ticketId = "..."
const TicketABI = "..." // you can get the ABI from the reference document

const TICKET_CONTRACT = getContract(ticketAddress, TicketABI, library, account)

const GAS_MARGIN = BigNumber.from(1000)

function calculateGasMargin(value: BigNumber, margin: BigNumber) {
  const offset = value.mul(margin).div(BigNumber.from(10000))
  return value.add(offset)
}

const handleStamp = () => {
  if (ticketAddress && ticketId !== undefined && TICKET_CONTRACT) {
    let estimate = TICKET_CONTRACT.estimateGas.stampTicket;
    let method = TICKET_CONTRACT.stampTicket;
    const ticketIdBN = BigNumber.from(ticketId)
    let args = [
      ticketIdBN
    ];
    let value = ethers.constants.Zero
    return estimate(...args, { value }).then((estimatedGasLimit: any) => {
      return method(...args, {
        value,
        gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN)
      })
    }).then((tx: any) => {
      return true
    }).catch((e: Error) => {
      console.log(e.message)
      return false
    })
  }
}
```


# Miscellaneous

## Signature verification

The purpose of signature verification is to ensure that the person submitting a HTTP request to your backend actually has ownership of the wallet address that he says he owns. This is done using Elliptic Curve Digital Signature Algorithm (ECDSA) to recover the address that could have signed a particular signature, and then checking if the address matches that was given in a HTTP request.

### The idea

Here, we outline an example implementation of how this can be done. The idea is that we ask the user to provide his wallet address, and the timestamp of the HTTP request. You may ask for other information if you desire. Then, we concatenate these two fields together, and generate a hash for it. We then ask the user to sign this hash, and produce a signature signed using his wallet address.

Then, in the HTTP request, we attach the plaintext address and timestamp, as well as the signature, into the header of the request. On the backend, we then re-generate the hash that was signed by the user. Then, we use a special Web3 function (akin to the ecrecover function in Solidity) to recover the address that signed the signature given, by supplying the re-generated hash. If everything matches, and the timestamp has not expired, then we allow the request to go through.

Doing the verification this way avoids the need for a centralised, traditional OAuth API to authenticate users, as it commonly is for Web3 technologies. Everything is secured via cryptography, just like in the blockchain itself.

### Example implementation&#x20;

**Frontend (React TSX)**

```tsx
import { useWeb3React } from '@web3-react/core'
import {
  safeAccess,
  getRawSignature,
  solidityKeccak,
  toUnixTimestamp
} from '../utils'

const { library } = useWeb3React()

const BACKEND_ADDRESS = "..."

const getHeaderFields = async (account, library) => {
    const currentTimestamp = toUnixTimestamp(new Date())
    
    const msg = solidityKeccak( ['address', 'uint256'], [account, currentTimestamp] )
    const signature = await getRawSignature(msg, library, account)
    
    return { address, signature, timestamp }
}

export async function getProtectedEndpoint(account, data) {
  const headers = await getHeaderFields(account, library)
  return axios.post(`${BACKEND_ADDRESS}/protected/`, data, {
    headers: {
      'Content-Type': 'application/json',
      'x-address': headers.address,
      'x-timestamp': headers.timestamp!.toString(),
      'x-signature': headers.signature
    }
  }).then((r) => {
    if (r.status === 200) {
      return r.data
    }

    return undefined
  }).catch((e: Error) => {
    console.log(e)
    return undefined
  })
}
```

**Backend (Python)**

```python
from web3 import Web3
from eth_account.messages import encode_defunct

REQUEST_TIMEOUT = 60 * 60 # 1 hour timeout

def verify_request(request):
    # Write permissions are only allowed to the owner of the wallet address
    try:
        address = request.META.get('HTTP_X_ADDRESS', None)
        timestamp = request.META.get('HTTP_X_TIMESTAMP', None)
        signature = request.META.get('HTTP_X_SIGNATURE', None)

        if (not (address and timestamp and signature)): # Missing fields
            return False

        if (Web3.toInt(hexstr=address) == 0): # Input address is 0
            return False

        # Use solidity keccak to hash the information
        msg = Web3.solidityKeccak(['address', 'uint256'], [address, int(timestamp)])
        
        # reconstruct signed hash using encode_defunct
        hash_ = encode_defunct(primitive = msg)

        # use ecrecover to recover the address that signed this signature
        recovered_address = w3.eth.account.recover_message(hash_, signature=signature)

        # get current time
        curr_time = int(time.time())

        # check if recovered address matches the address given, and that the timeout has not passed
        return recovered_address == address and curr_time < (int(timestamp) + REQUEST_TIMEOUT)
    except:
        return False
```

## Getting a smart contract instance with ethers

{% tabs %}
{% tab title="React TSX" %}

```tsx
// account is optional
export function getContract(address: string, ABI: any, library: any, account: any) {
  if (!isAddress(address) || address === ethers.constants.AddressZero) {
    throw Error(`Invalid 'address' parameter '${address}'.`)
  }

  return new ethers.Contract(address, ABI, getProviderOrSigner(library, account))
}
```

{% endtab %}
{% endtabs %}


# Graph Node API

This section outlines the schema of commonly queried entities stored in the GraphQL database.

## Schemas

For the remaining schema of other entities, you can go to the GraphQL playground, and click on the "Docs". Then, click on "query", and you can explore the schema of all entities possible.

{% content-ref url="/pages/NknoY0HeqgpLCihxGN4u" %}
[TKETSFactory](/reference/graph-node-api/tketsfactory)
{% endcontent-ref %}

{% content-ref url="/pages/CHmwBxQnjgTVhDAQp66l" %}
[Event](/reference/graph-node-api/event)
{% endcontent-ref %}

{% content-ref url="/pages/HkP0VUaNzn1D0lGkH2bp" %}
[Ticket](/reference/graph-node-api/ticket)
{% endcontent-ref %}

{% content-ref url="/pages/6AKbhptFk65MYwjjxIvN" %}
[TicketToken](/reference/graph-node-api/tickettoken)
{% endcontent-ref %}


# TKETSFactory

### **ID**

The ID of the factory (there should only be one factory). Type: ID.

### eventCount

Total number of events of the factory. Type: Int.

### totalVolumeTFUEL

Total volume of TFUEL transacted on the platform. Type: BigDecimal.

### commissionRate

The current commission rate of the platform. Type: BigInt.

### totalTicketMint

Total number of tickets minted. Type: BigInt.

### totalTicketTransfers

Total number of ticket transfers (including sales on third party marketplaces). Type: BigInt.

### totalTicketStamps

Total number of stamped tickets. Type: BigInt.

### txCount

Total number of all transactions done on the platform. Type: BigInt.


# Event

### **ID**

The ID of the event, converted from a uint160 into a string. Must be lowercase. Type: ID.

### owner

The wallet address that currently owns this event. Type: Bytes.

### timeStart

The starting time of the event. Type: BigInt.

### timeEnd

The ending time of the event. Type: BigInt.

### status

The current status of the event. If true, the event is currently cancelled. Type: Boolean.

### tickets

A list of tickets that the event has. Type: \[Ticket].

### stampers

A list of addresses that are authorised to stamp for the event on the owner's behalf. Type: \[Bytes].

### tradeVolume

Total volume of all transactions performed for this event. Type: BigDecimal.

### createdAtTimestamp

Unix timestamp of the block where this event was created. Type: BigInt.

### createdAtBlockNumber

Block number of the block where this event was created. Type: BigInt.

### txCount

Total number of all transactions done on this event. Type: BigInt.

### eventDayData

A list of summarised daily statistics produced for each event. Type: \[EventDayData].


# Ticket

### I**D**

The ID of the ticket, converted from a Ethereum address into a string. Must be lowercase. Type: ID.

### event

The event that contains this ticket. Type: Event.

### maxTickets

The maximum number of tickets that can be minted. If set to 0, the number of minted tickets is unbounded. Type: BigInt.

### ticketPrice

The price of each ticket in Wei. Type: BigInt.

### ticketStartTime

The starting unix timestamp of the ticket sale. Type: BigInt.

### ticketEndTime

The ending unix timestamp of the ticket sale. Type: BigInt.

### acceptDonations

Checks if a ticket can accept donations on top of the listed price. If false, sending TFUEL above the listed price will revert the transaction. Type: Boolean.

### uri

The NFT metadata URI that the ticket has. Type: String.

### uriHash

A hash of the URI content, to verify that it has not been tampered with. Type: Bytes.

### useTokenIDInURI

Checks if the tokenID should be included in the URI. If true, the token ID will be appended to the URI when retrieving NFT media. Used for tickets that have a unique URI for each token ID. Type: Boolean.

### refundPrice

The price of the refund that is set by the owner. Type: BigInt.

### allowRefunds

Checks if a ticket can be refunded. Type: Boolean.

### createdAtTimestamp

Timestamp of the block where this ticket was created. Type: BigInt.

### createdAtBlockNumber

Block number of the block where this ticket was created. Type: BigInt.

### ticketTokens

A list of all ticket tokens that were minted for this ticket. Type: \[TicketToken].

### totalSupply

Current total supply of this ticket. Type: BigInt.

### saleVolume

Current total sale volume of this ticket. Type: BigDecimal.

### balanceTfuel

Current balance in TFUEL of the smart contract of this ticket. Type: BigDecimal.

### txCount

Total number of all transactions done on this ticket. Type: BigInt.

### ticketHourData

A list of summarised hourly statistics produced for each ticket. Type: \[TicketHourData].

### mints

A list of mint transactions for this ticket. Type: \[Mint].

### transfers

A list of transfer transactions for this ticket. Type: \[Transfer].

### stamps

A list of stamp transactions for this ticket. Type: \[Stamp].


# TicketToken

### I**D**

The ID of the ticket token, created using the following format - "{ticketAddress}#{tokenID}". Must be lowercase. Type: ID.

### event

The event that contains this ticket token. Type: Event.

### ticket

The ticket that this token is minted from. Type: Ticket.

### tokenID

The ID of the ticket token that was minted. Type: BigInt.

### tokenURI

The URI of the ticket token that was minted. Type: String.

### owner

The current owner of the ticket token. Type: User

### stamped

A boolean indicating if this ticket token was stamped or not. Type: User

### mints

A list of mint transactions for this particular ticket token only (and therefore, there should be only one). Type: \[Mint].

### transfers

A list of transfer transactions for this this particular ticket token only. Type: \[Transfer].

### stamps

A list of stamp transactions for this this particular ticket token only (and therefore, there should be only one). Type: \[Stamp].


# Smart Contract Specifications

This section outlines the function signatures and structs that you need to interact with our smart contracts directly.

## EventFactory

This smart contract is responsible for tracking the ownership of each event, as well as mapping each ticket to the event it is under. It is also responsible for the creation of new Ticket smart contracts.

{% content-ref url="/pages/ZQ7M2WEt8cGBcyJuPQw6" %}
[EventFactory](/reference/smart-contract-specifications/eventfactory)
{% endcontent-ref %}

## Ticket

This smart contract extends the ERC-721 NFT specification, with a few additional ticketing-related functions.

{% content-ref url="/pages/wWg05GyWxdF60sw2Ftx9" %}
[Ticket](/reference/smart-contract-specifications/ticket)
{% endcontent-ref %}


# EventFactory

### Function signatures

#### `createEvent(FactoryStructs.EventMetadata calldata _metadata)`

Creates an event using the metadata provided. Sets the owner of the event to `msg.sender`.

#### `transferOwnership(uint160 eventId, address _newOwner)`

Transfers the ownership of an event to a new address. Only callable by the owner of an event.

#### `cancelEvent(uint160 eventId)`

Cancels an event, and enables refunds. Only callable by the owner of an event.

#### `createTicket(uint160 eventId, string calldata uri, bytes32 uriHash, bool useTokenIDInURI, uint256 _ticketPrice, FactoryStructs.TicketMetadata calldata _ticketMetadata)`

Creates a ticket smart contract using the provided data. Only callable by the owner of an event.

#### `validateTicket(uint160 eventId, address holder, Ticket ticket, uint256 ticketId, uint256 timestamp, uint8 v, bytes32 r, bytes32 s)`

Validates a ticket using the provided data and signature. This is a view function that costs no gas.

#### `isStamperAuthorized(address stamper, uint160 eventId)`

Check if a stamper is authorised for an event. This is a view function that costs no gas.

#### `addStamperToEvent(address stamper, uint160 eventId)`

Adds a stamper to an event. Only callable by the owner of an event.

#### `removeStamperFromEvent(address stamper, uint160 eventId)`

Removes a stamper from an event. Only callable by the owner of an event.

### Structs

```
library FactoryStructs {
    struct EventMetadata {
        uint256 timeStart;
        uint256 timeEnd;
    }
    
    struct TicketMetadata {
        uint256 maxTickets;
        uint256 ticketStartTime;
        uint256 ticketEndTime;
        bool acceptDonations;
        bool allowRefunds;
    }
}
```


# ABI

## Smart Contract ABI

Please use the following ABI for making smart contract calls with our EventFactory smart contract.

```
[
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "newCommissionRate",
          "type": "uint256"
        }
      ],
      "name": "CommissionRateChange",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        }
      ],
      "name": "EventCancel",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "ownerAddress",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "timeStart",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "timeEnd",
          "type": "uint256"
        }
      ],
      "name": "EventCreate",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "previousOwner",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "OwnershipTransferred",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "stamperAddress",
          "type": "address"
        }
      ],
      "name": "StamperAdd",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "stamperAddress",
          "type": "address"
        }
      ],
      "name": "StamperRemove",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "ownerAddress",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "indexed": true,
          "internalType": "contract Ticket",
          "name": "ticketAddress",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "string",
          "name": "uri",
          "type": "string"
        },
        {
          "indexed": false,
          "internalType": "bytes32",
          "name": "uriHash",
          "type": "bytes32"
        },
        {
          "indexed": false,
          "internalType": "bool",
          "name": "useTokenIDInURI",
          "type": "bool"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "maxTickets",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "ticketPrice",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "ticketStartTime",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "ticketEndTime",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "bool",
          "name": "acceptDonations",
          "type": "bool"
        },
        {
          "indexed": false,
          "internalType": "bool",
          "name": "allowRefunds",
          "type": "bool"
        }
      ],
      "name": "TicketCreate",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "CANNOT_TRANSFER_TO_ZERO_ADDRESS",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [],
      "name": "INITIALIZATION_ERROR",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [],
      "name": "INVALID_INPUT",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [],
      "name": "NOT_EXISTS",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [],
      "name": "TKETSOwner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [],
      "name": "UNAUTHORIZED",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [],
      "name": "VALIDATION_TIMEOUT",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [],
      "name": "commissionRate",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [],
      "name": "currentEventCount",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [
        {
          "internalType": "uint160",
          "name": "",
          "type": "uint160"
        }
      ],
      "name": "eventToMetadata",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "timeStart",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "timeEnd",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [
        {
          "internalType": "uint160",
          "name": "",
          "type": "uint160"
        }
      ],
      "name": "eventToOwner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [
        {
          "internalType": "uint160",
          "name": "",
          "type": "uint160"
        }
      ],
      "name": "eventToStatus",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "stateMutability": "payable",
      "type": "receive",
      "payable": true
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_rate",
          "type": "uint256"
        }
      ],
      "name": "setCommissionRate",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "withdrawCommissions",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "transferTKETSOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "internalType": "address",
          "name": "eventOwner",
          "type": "address"
        },
        {
          "components": [
            {
              "internalType": "uint256",
              "name": "timeStart",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "timeEnd",
              "type": "uint256"
            }
          ],
          "internalType": "struct FactoryStructs.EventMetadata",
          "name": "_metadata",
          "type": "tuple"
        }
      ],
      "name": "forceCreateEvent",
      "outputs": [
        {
          "internalType": "uint160",
          "name": "uid",
          "type": "uint160"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "uint256",
              "name": "timeStart",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "timeEnd",
              "type": "uint256"
            }
          ],
          "internalType": "struct FactoryStructs.EventMetadata",
          "name": "_metadata",
          "type": "tuple"
        }
      ],
      "name": "createEvent",
      "outputs": [
        {
          "internalType": "uint160",
          "name": "uid",
          "type": "uint160"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "internalType": "address",
          "name": "_newOwner",
          "type": "address"
        }
      ],
      "name": "transferOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        }
      ],
      "name": "cancelEvent",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "internalType": "string",
          "name": "uri",
          "type": "string"
        },
        {
          "internalType": "bytes32",
          "name": "uriHash",
          "type": "bytes32"
        },
        {
          "internalType": "bool",
          "name": "useTokenIDInURI",
          "type": "bool"
        },
        {
          "internalType": "uint256",
          "name": "_ticketPrice",
          "type": "uint256"
        },
        {
          "components": [
            {
              "internalType": "uint256",
              "name": "maxTickets",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "ticketStartTime",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "ticketEndTime",
              "type": "uint256"
            },
            {
              "internalType": "bool",
              "name": "acceptDonations",
              "type": "bool"
            },
            {
              "internalType": "bool",
              "name": "allowRefunds",
              "type": "bool"
            }
          ],
          "internalType": "struct FactoryStructs.TicketMetadata",
          "name": "_ticketMetadata",
          "type": "tuple"
        }
      ],
      "name": "createTicket",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "internalType": "contract Ticket",
          "name": "ticket",
          "type": "address"
        }
      ],
      "name": "forceCreateTicketFromAddress",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "internalType": "address",
          "name": "holder",
          "type": "address"
        },
        {
          "internalType": "contract Ticket",
          "name": "ticket",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "ticketId",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "timestamp",
          "type": "uint256"
        },
        {
          "internalType": "uint8",
          "name": "v",
          "type": "uint8"
        },
        {
          "internalType": "bytes32",
          "name": "r",
          "type": "bytes32"
        },
        {
          "internalType": "bytes32",
          "name": "s",
          "type": "bytes32"
        }
      ],
      "name": "validateTicket",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "stamper",
          "type": "address"
        },
        {
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        }
      ],
      "name": "isStamperAuthorized",
      "outputs": [
        {
          "internalType": "bool",
          "name": "authorized",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function",
      "constant": true
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "stamper",
          "type": "address"
        },
        {
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        }
      ],
      "name": "addStamperToEvent",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "stamper",
          "type": "address"
        },
        {
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        }
      ],
      "name": "removeStamperFromEvent",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint160",
          "name": "eventId",
          "type": "uint160"
        },
        {
          "internalType": "address",
          "name": "holder",
          "type": "address"
        },
        {
          "internalType": "contract Ticket",
          "name": "ticket",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "ticketId",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "timestamp",
          "type": "uint256"
        }
      ],
      "name": "encodeMsg",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "message",
          "type": "bytes32"
        }
      ],
      "stateMutability": "pure",
      "type": "function",
      "constant": true
    }
  ]
```


# Ticket

#### **`eventId()`**

Gets the event ID of the smart contract

#### `useTokenIDInURI()`

Gets whether the token ID should be included in the Token ID

#### `ticketPrice()`

Gets the current ticket price in Wei

#### `refundPrice()`

Gets the current refund price in Wei

#### `mintTicket(uint256 numberOfTickets)`

Mints `numberOfTickets` of tickets. Requires the value of the call to match the price expected.

#### `changeTicketPrice(uint256 _newTicketPrice)`

Change the price of the ticket in Wei. Only callable by the owner of the event.

#### `changeRefundPrice(uint256 _newRefundPrice)`

Change the refund price of the ticket. Only callable by the owner of the event.

#### `stampTicket(uint256 ticketId)`

Marks a ticket as stamped. Only callable by the owner of the event, or the authorised stampers of the event.

#### `transferFrom(address _from, address _to, uint256 tokenId)`

Transfers a ticket with token ID from an address to another. Only callable by the owner of the ticket token, or the approved sender of the ticket token.

#### `tokenURI(uint256 tokenId)`

Gets the tokenURI of a token ID.

#### `withdrawBalance()`

Withdraws the balance of the smart contract to the owner's address. Only callable by the owner of the event.

#### `refundTicket(uint256 tokenId)`

Refunds a ticket for the refund price. Only callable by the owner of the ticket token, and if the event has been cancelled.

#### `refundAll()`

Refunds up to 5 tickets at once for the refund price. Only callable by the owner of the ticket token, and if the event has been cancelled.

#### `depositBalance()`

Deposits a sum of TFUEL into the smart contract address, for refund purposes. Only callable by the owner of the event.


# ABI

## Smart Contract ABI

Please use the following ABI for making smart contract calls with our Ticket smart contracts. Otherwise, you may also use the ERC-721 or TNT-721 smart contract ABIs if you only require the standard interface.

```
[
  {
    "inputs": [
      {
        "internalType": "contract EventFactory",
        "name": "_factory",
        "type": "address"
      },
      {
        "internalType": "uint160",
        "name": "_eventId",
        "type": "uint160"
      },
      {
        "internalType": "string",
        "name": "uri",
        "type": "string"
      },
      {
        "internalType": "bytes32",
        "name": "_uriHash",
        "type": "bytes32"
      },
      {
        "internalType": "bool",
        "name": "_useTokenIDInURI",
        "type": "bool"
      },
      {
        "internalType": "uint256",
        "name": "_ticketPrice",
        "type": "uint256"
      },
      {
        "components": [
          {
            "internalType": "uint256",
            "name": "maxTickets",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "ticketStartTime",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "ticketEndTime",
            "type": "uint256"
          },
          {
            "internalType": "bool",
            "name": "acceptDonations",
            "type": "bool"
          },
          {
            "internalType": "bool",
            "name": "allowRefunds",
            "type": "bool"
          }
        ],
        "internalType": "struct FactoryStructs.TicketMetadata",
        "name": "_ticketMetadata",
        "type": "tuple"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "approved",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "approved",
        "type": "bool"
      }
    ],
    "name": "ApprovalForAll",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "newRefundPrice",
        "type": "uint256"
      }
    ],
    "name": "ChangeRefundPrice",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "newTicketPrice",
        "type": "uint256"
      }
    ],
    "name": "ChangeTicketPrice",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "depositAmount",
        "type": "uint256"
      }
    ],
    "name": "DepositBalance",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "mintedAddress",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "ticketId",
        "type": "uint256"
      }
    ],
    "name": "TicketMint",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "refundedAddress",
        "type": "address"
      }
    ],
    "name": "TicketRefund",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "ticketId",
        "type": "uint256"
      }
    ],
    "name": "TicketStamped",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [],
    "name": "WithdrawBalance",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "CANNOT_TRANSFER_TO_ZERO_ADDRESS",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "INVALID_ACTION",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "TICKET_SALE_ERROR",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "UNAUTHORIZED",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "approve",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "baseURI",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "eventId",
    "outputs": [
      {
        "internalType": "uint160",
        "name": "",
        "type": "uint160"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "getApproved",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "operator",
        "type": "address"
      }
    ],
    "name": "isApprovedForAll",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "metadata",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "maxTickets",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "ticketStartTime",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "ticketEndTime",
        "type": "uint256"
      },
      {
        "internalType": "bool",
        "name": "acceptDonations",
        "type": "bool"
      },
      {
        "internalType": "bool",
        "name": "allowRefunds",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "ownerOf",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "refundPrice",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "safeTransferFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "internalType": "bytes",
        "name": "_data",
        "type": "bytes"
      }
    ],
    "name": "safeTransferFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "approved",
        "type": "bool"
      }
    ],
    "name": "setApprovalForAll",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes4",
        "name": "interfaceId",
        "type": "bytes4"
      }
    ],
    "name": "supportsInterface",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "ticketPrice",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "index",
        "type": "uint256"
      }
    ],
    "name": "tokenByIndex",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "index",
        "type": "uint256"
      }
    ],
    "name": "tokenOfOwnerByIndex",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "tokenToStamped",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "useTokenIDInURI",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "numberOfTickets",
        "type": "uint256"
      }
    ],
    "name": "mintTicket",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_newTicketPrice",
        "type": "uint256"
      }
    ],
    "name": "changeTicketPrice",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_newRefundPrice",
        "type": "uint256"
      }
    ],
    "name": "changeRefundPrice",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "ticketId",
        "type": "uint256"
      }
    ],
    "name": "stampTicket",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "transferFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "tokenURI",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "withdrawBalance",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "refundTicket",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "refundAll",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "depositBalance",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  }
]
```


