├── .commitlintrc.json ├── .eslintignore ├── .eslintrc ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── build.yml │ ├── format.yml │ └── lint.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .prettierignore ├── .prettierrc ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── lerna.json ├── package.json ├── subgraphs ├── blocks │ ├── abis │ │ └── BSCValidatorSet.json │ ├── mappings │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml ├── exchange │ ├── abis │ │ ├── ERC20.json │ │ ├── ERC20NameBytes.json │ │ ├── ERC20SymbolBytes.json │ │ ├── Factory.json │ │ └── Pair.json │ ├── mappings │ │ ├── core.ts │ │ ├── dayUpdates.ts │ │ ├── factory.ts │ │ ├── pricing.ts │ │ └── utils │ │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml ├── farm-auctions │ ├── abis │ │ └── FarmAuction.json │ ├── mappings │ │ ├── index.ts │ │ └── utils │ │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml ├── lottery │ ├── abis │ │ └── Lottery.json │ ├── mappings │ │ ├── index.ts │ │ └── utils │ │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml ├── masterchef-v2 │ ├── abis │ │ └── MasterChefV2.json │ ├── package.json │ ├── schema.graphql │ ├── src │ │ ├── entities │ │ │ ├── master-chef.ts │ │ │ ├── pool.ts │ │ │ └── user.ts │ │ ├── mappings │ │ │ └── masterchefV2.ts │ │ └── utils.ts │ └── subgraph.yaml ├── nft-market │ ├── abis │ │ ├── ERC721NFTMarketV1.json │ │ ├── IERC721.json │ │ └── PancakeBunnies.json │ ├── mappings │ │ ├── index.ts │ │ └── utils │ │ │ ├── dayUpdates.ts │ │ │ ├── erc721.ts │ │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml ├── pairs │ ├── abis │ │ ├── ERC20.json │ │ └── Factory.json │ ├── mappings │ │ ├── factory.ts │ │ └── utils │ │ │ └── erc20.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml ├── pancake-squad │ ├── abis │ │ └── ERC721.json │ ├── mappings │ │ ├── index.ts │ │ └── utils │ │ │ ├── erc-721.ts │ │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml ├── prediction │ ├── v1 │ │ ├── abis │ │ │ └── Prediction.json │ │ ├── mappings │ │ │ └── index.ts │ │ ├── package.json │ │ ├── schema.graphql │ │ └── subgraph.yaml │ └── v2 │ │ ├── abis │ │ └── PredictionV2.json │ │ ├── mappings │ │ └── index.ts │ │ ├── package.json │ │ ├── schema.graphql │ │ └── subgraph.yaml ├── profile │ ├── abis │ │ └── Profile.json │ ├── mappings │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml ├── smartchef │ ├── abis │ │ ├── ERC20.json │ │ ├── ERC20NameBytes.json │ │ ├── ERC20SymbolBytes.json │ │ ├── SmartChef.json │ │ └── SmartChefFactory.json │ ├── mappings │ │ ├── factory.ts │ │ ├── index.ts │ │ └── utils │ │ │ ├── erc20.ts │ │ │ ├── index.ts │ │ │ ├── smartchef.ts │ │ │ └── user.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml ├── timelock │ ├── abis │ │ └── Timelock.json │ ├── mappings │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml └── trading-competition │ ├── v1 │ ├── abis │ │ ├── Factory.json │ │ ├── Pair.json │ │ └── TradingCompetitionV1.json │ ├── mappings │ │ ├── competition.ts │ │ ├── pair.ts │ │ └── utils │ │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml │ ├── v2 │ ├── abis │ │ ├── Factory.json │ │ ├── Pair.json │ │ └── TradingCompetitionV2.json │ ├── mappings │ │ ├── competition.ts │ │ ├── pair.ts │ │ └── utils │ │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml │ ├── v3 │ ├── abis │ │ ├── Factory.json │ │ ├── Pair.json │ │ └── TradingCompetitionV3.json │ ├── mappings │ │ ├── competition.ts │ │ ├── pair.ts │ │ └── utils │ │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml │ └── v4 │ ├── abis │ ├── Factory.json │ ├── Pair.json │ └── TradingCompetitionV4.json │ ├── mappings │ ├── competition.ts │ ├── pair.ts │ └── utils │ │ └── index.ts │ ├── package.json │ ├── schema.graphql │ └── subgraph.yaml ├── tsconfig.json └── yarn.lock /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@commitlint/config-conventional"], 3 | "rules": { 4 | "subject-case": [2, "always", "sentence-case"], 5 | "type-enum": [ 6 | 2, 7 | "always", 8 | ["build", "ci", "chore", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test"] 9 | ] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/ 2 | generated/ 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "plugins": ["@typescript-eslint"], 4 | "extends": ["plugin:@typescript-eslint/recommended", "prettier"] 5 | } 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in 2 | # the repo. Unless a later match takes precedence, 3 | # @global-owner1 and @global-owner2 will be requested for 4 | # review when someone opens a pull request. 5 | * @ChefKai 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | # Maintain dependencies for GitHub Actions 5 | - package-ecosystem: "github-actions" 6 | directory: "/" 7 | schedule: 8 | interval: "monthly" 9 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - v2 9 | 10 | jobs: 11 | build: 12 | 13 | name: Build 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v2 19 | 20 | - name: Setup Node 21 | uses: actions/setup-node@v2 22 | with: 23 | node-version: 14.x 24 | 25 | - name: Get yarn cache directory path 26 | id: yarn-cache-dir-path 27 | run: echo "::set-output name=dir::$(yarn cache dir)" 28 | 29 | - uses: actions/cache@v2 30 | id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) 31 | with: 32 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 33 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 34 | restore-keys: | 35 | ${{ runner.os }}-yarn- 36 | 37 | - name: Install dependencies 38 | run: yarn install --frozen-lockfile 39 | 40 | - name: Run codegen 41 | run: yarn codegen 42 | 43 | - name: Run build 44 | run: yarn build 45 | -------------------------------------------------------------------------------- /.github/workflows/format.yml: -------------------------------------------------------------------------------- 1 | name: Format 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - v2 9 | 10 | jobs: 11 | format: 12 | 13 | name: Prettier 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v2 19 | 20 | - name: Setup Node 21 | uses: actions/setup-node@v2 22 | with: 23 | node-version: 14.x 24 | 25 | - name: Get yarn cache directory path 26 | id: yarn-cache-dir-path 27 | run: echo "::set-output name=dir::$(yarn cache dir)" 28 | 29 | - uses: actions/cache@v2 30 | id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) 31 | with: 32 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 33 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 34 | restore-keys: | 35 | ${{ runner.os }}-yarn- 36 | 37 | - name: Install dependencies 38 | run: yarn install --frozen-lockfile 39 | 40 | - name: Run Prettier 41 | run: yarn format:check 42 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - v2 9 | 10 | jobs: 11 | lint: 12 | 13 | name: ESLint 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v2 19 | 20 | - name: Setup Node 21 | uses: actions/setup-node@v2 22 | with: 23 | node-version: 14.x 24 | 25 | - name: Get yarn cache directory path 26 | id: yarn-cache-dir-path 27 | run: echo "::set-output name=dir::$(yarn cache dir)" 28 | 29 | - uses: actions/cache@v2 30 | id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) 31 | with: 32 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 33 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 34 | restore-keys: | 35 | ${{ runner.os }}-yarn- 36 | 37 | - name: Install dependencies 38 | run: yarn install --frozen-lockfile 39 | 40 | - name: Run ESLint 41 | run: yarn lint 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Vercel build output 79 | .vercel 80 | 81 | # Next.js build output 82 | .next 83 | 84 | # Nuxt.js build / generate output 85 | .nuxt 86 | dist 87 | 88 | # Gatsby files 89 | .cache/ 90 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 91 | # https://nextjs.org/blog/next-9-1#public-directory-support 92 | # public 93 | 94 | # vuepress build output 95 | .vuepress/dist 96 | 97 | # Serverless directories 98 | .serverless/ 99 | 100 | # FuseBox cache 101 | .fusebox/ 102 | 103 | # DynamoDB Local files 104 | .dynamodb/ 105 | 106 | # TernJS port file 107 | .tern-port 108 | 109 | # MacOS 110 | .DS_Store 111 | 112 | # IDE's 113 | .vscode/ 114 | .idea/ 115 | 116 | # GraphQL directories 117 | build/ 118 | generated/ 119 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn commitlint --edit $1 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn format:check 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build/ 2 | generated/ 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120 3 | } 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement. 63 | All complaints will be reviewed and investigated promptly and fairly. 64 | 65 | All community leaders are obligated to respect the privacy and security of the 66 | reporter of any incident. 67 | 68 | ## Enforcement Guidelines 69 | 70 | Community leaders will follow these Community Impact Guidelines in determining 71 | the consequences for any action they deem in violation of this Code of Conduct: 72 | 73 | ### 1. Correction 74 | 75 | **Community Impact**: Use of inappropriate language or other behavior deemed 76 | unprofessional or unwelcome in the community. 77 | 78 | **Consequence**: A private, written warning from community leaders, providing 79 | clarity around the nature of the violation and an explanation of why the 80 | behavior was inappropriate. A public apology may be requested. 81 | 82 | ### 2. Warning 83 | 84 | **Community Impact**: A violation through a single incident or series 85 | of actions. 86 | 87 | **Consequence**: A warning with consequences for continued behavior. No 88 | interaction with the people involved, including unsolicited interaction with 89 | those enforcing the Code of Conduct, for a specified period of time. This 90 | includes avoiding interactions in community spaces as well as external channels 91 | like social media. Violating these terms may lead to a temporary or 92 | permanent ban. 93 | 94 | ### 3. Temporary Ban 95 | 96 | **Community Impact**: A serious violation of community standards, including 97 | sustained inappropriate behavior. 98 | 99 | **Consequence**: A temporary ban from any sort of interaction or public 100 | communication with the community for a specified period of time. No public or 101 | private interaction with the people involved, including unsolicited interaction 102 | with those enforcing the Code of Conduct, is allowed during this period. 103 | Violating these terms may lead to a permanent ban. 104 | 105 | ### 4. Permanent Ban 106 | 107 | **Community Impact**: Demonstrating a pattern of violation of community 108 | standards, including sustained inappropriate behavior, harassment of an 109 | individual, or aggression toward or disparagement of classes of individuals. 110 | 111 | **Consequence**: A permanent ban from any sort of public interaction within 112 | the community. 113 | 114 | ## Attribution 115 | 116 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 117 | version 2.0, available at 118 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 119 | 120 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 121 | enforcement ladder](https://github.com/mozilla/diversity). 122 | 123 | [homepage]: https://www.contributor-covenant.org 124 | 125 | For answers to common questions about this code of conduct, see the FAQ at 126 | https://www.contributor-covenant.org/faq. Translations are available at 127 | https://www.contributor-covenant.org/translations. 128 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PancakeSwap Subgraph 2 | 3 | TheGraph exposes a GraphQL endpoint to query the events and entities within the Binance Smart Chain and PancakeSwap ecosystem. 4 | 5 | Currently, there are multiple subgraphs, but additional subgraphs can be added to this repository, following the current architecture. 6 | 7 | ## Subgraphs 8 | 9 | 1. **[Blocks](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/blocks)**: Tracks all blocks on Binance Smart Chain. 10 | 11 | 2. **[Exchange](https://pancakeswap.medium.com/pancakeswap-info-relaunch-in-partnership-with-150-000-bounty-winner-streamingfast-f7892559d388)**: Tracks all PancakeSwap Exchange data with price, volume, liquidity, ... 12 | 13 | 3. **[Farm Auctions](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/farm-auctions)**: Tracks all PancakeSwap Farm Auctions with auctions and bids. 14 | 15 | 4. **[Lottery](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/lottery)**: Tracks all PancakeSwap Lottery with rounds, draws and tickets. 16 | 17 | 5. **[NFT Market (v1)](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/nft-market)**: Tracks all PancakeSwap NFT Market for ERC-721. 18 | 19 | 6. **[Pairs](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/pairs)**: Tracks all PancakeSwap Pairs and Tokens. 20 | 21 | 7. **[Pancake Squad](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/pancake-squad)**: Tracks all Pancake Squad metrics with Owners, Tokens (including metadata), and Transactions. 22 | 23 | 8. **[Prediction (v1)](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/prediction)**: Tracks all PancakeSwap Prediction (v1) with market, rounds, and bets. 24 | 25 | 9. **[Prediction (v2)](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/prediction-v2)**: Tracks all PancakeSwap Prediction (v2) with market, rounds, and bets. 26 | 27 | 10. **[Profile](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/profile)**: Tracks all PancakeSwap Profile with teams, users, points and campaigns. 28 | 29 | 11. **[SmartChef](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/smartchef)**: Tracks all PancakeSwap SmartChef (a.k.a. Syrup Pools) with tokens and rewards. 30 | 31 | 12. **[Timelock](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/timelock)**: Tracks all PancakeSwap Timelock queued, executed, and cancelled transactions. 32 | 33 | 13. **[Trading Competition (v1)](https://thegraph.com/legacy-explorer/subgraph/pancakeswap/trading-competition-v1)**: Tracks all metrics for the Easter Battle (April 07—14, 2021). 34 | 35 | 14. **[MasterChef (v2)](https://thegraph.com/hosted-service/subgraph/pancakeswap/masterchef-v2)**: Tracks data for MasterChefV2. 36 | 37 | 38 | ## Dependencies 39 | 40 | - [Graph CLI](https://github.com/graphprotocol/graph-cli) 41 | - Required to generate and build local GraphQL dependencies. 42 | 43 | ```shell 44 | yarn global add @graphprotocol/graph-cli 45 | ``` 46 | 47 | ## Deployment 48 | 49 | For any of the subgraph: `blocks` as `[subgraph]` 50 | 51 | 1. Run the `cd subgraphs/[subgraph]` command to move to the subgraph directory. 52 | 53 | 2. Run the `yarn codegen` command to prepare the TypeScript sources for the GraphQL (generated/*). 54 | 55 | 3. Run the `yarn build` command to build the subgraph, and check compilation errors before deploying. 56 | 57 | 4. Run `graph auth --product hosted-service ''` 58 | 59 | 5. Deploy via `yarn deploy`. 60 | 61 | ## v1 62 | 63 | To access subgraphs related to PancakeSwap v1 ecosystem ([article](https://pancakeswap.medium.com/the-great-migration-vote-4093cb3edf23)), use [`v1`](https://github.com/pancakeswap/pancake-subgraph/tree/v1) branch. 64 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "packages": [ 4 | "subgraphs/**/*" 5 | ], 6 | "useWorkspaces": true, 7 | "version": "independent" 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pancake-subgraph", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "2.0.0", 5 | "private": true, 6 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 7 | "author": "PancakeSwap", 8 | "license": "GPL-3.0-or-later", 9 | "workspaces": [ 10 | "subgraphs/**/*" 11 | ], 12 | "scripts": { 13 | "codegen": "lerna run codegen", 14 | "build": "lerna run build", 15 | "format:check": "prettier --check '*/**/*.{js,ts}'", 16 | "format:write": "prettier --write '*/**/*.{js,ts}'", 17 | "lint": "eslint '*/**/*.{js,ts}'", 18 | "prepare": "husky install" 19 | }, 20 | "devDependencies": { 21 | "@commitlint/cli": "^13.1.0", 22 | "@commitlint/config-conventional": "^13.1.0", 23 | "@graphprotocol/graph-cli": "^0.21.0", 24 | "@graphprotocol/graph-ts": "^0.20.0", 25 | "@typescript-eslint/eslint-plugin": "^4.31.0", 26 | "@typescript-eslint/parser": "^4.31.0", 27 | "eslint": "^7.32.0", 28 | "eslint-config-prettier": "^8.3.0", 29 | "husky": "^7.0.0", 30 | "lerna": "^4.0.0", 31 | "prettier": "^2.4.0", 32 | "typescript": "^4.3.5" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /subgraphs/blocks/mappings/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { ethereum } from "@graphprotocol/graph-ts"; 3 | import { Block } from "../generated/schema"; 4 | 5 | export function handleBlock(block: ethereum.Block): void { 6 | let entity = new Block(block.hash.toHex()); 7 | entity.parentHash = block.parentHash; 8 | entity.unclesHash = block.unclesHash; 9 | entity.author = block.author; 10 | entity.stateRoot = block.stateRoot; 11 | entity.transactionsRoot = block.transactionsRoot; 12 | entity.receiptsRoot = block.receiptsRoot; 13 | entity.number = block.number; 14 | entity.gasUsed = block.gasUsed; 15 | entity.gasLimit = block.gasLimit; 16 | entity.timestamp = block.timestamp; 17 | entity.difficulty = block.difficulty; 18 | entity.totalDifficulty = block.totalDifficulty; 19 | entity.size = block.size; 20 | entity.save(); 21 | } 22 | -------------------------------------------------------------------------------- /subgraphs/blocks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blocks", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/blocks subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/blocks/schema.graphql: -------------------------------------------------------------------------------- 1 | """ 2 | Binance Smart Chain blocks 3 | """ 4 | type Block @entity { 5 | "ID (hash)" 6 | id: ID! 7 | "Parent Hash" 8 | parentHash: Bytes! 9 | "Uncles Hash" 10 | unclesHash: Bytes! 11 | "Author" 12 | author: Bytes! 13 | "State Root" 14 | stateRoot: Bytes! 15 | "Transactions Root" 16 | transactionsRoot: Bytes! 17 | "Receipts Root" 18 | receiptsRoot: Bytes! 19 | "Number" 20 | number: BigInt! 21 | "Gas Used" 22 | gasUsed: BigInt! 23 | "Gas Limit" 24 | gasLimit: BigInt! 25 | "Timestamp" 26 | timestamp: BigInt! 27 | "Difficulty" 28 | difficulty: BigInt! 29 | "Total Difficulty" 30 | totalDifficulty: BigInt! 31 | "Size" 32 | size: BigInt 33 | } 34 | -------------------------------------------------------------------------------- /subgraphs/blocks/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Binance Smart Chain Blocks 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: BSCValidatorSet 9 | network: bsc 10 | source: 11 | address: '0x0000000000000000000000000000000000001000' 12 | abi: BSCValidatorSet 13 | mapping: 14 | kind: ethereum/events 15 | apiVersion: 0.0.4 16 | language: wasm/assemblyscript 17 | file: ./mappings/index.ts 18 | entities: 19 | - Block 20 | abis: 21 | - name: BSCValidatorSet 22 | file: ./abis/BSCValidatorSet.json 23 | blockHandlers: 24 | - handler: handleBlock 25 | -------------------------------------------------------------------------------- /subgraphs/exchange/abis/ERC20.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "name", 6 | "outputs": [ 7 | { 8 | "name": "", 9 | "type": "string" 10 | } 11 | ], 12 | "payable": false, 13 | "stateMutability": "view", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": false, 18 | "inputs": [ 19 | { 20 | "name": "_spender", 21 | "type": "address" 22 | }, 23 | { 24 | "name": "_value", 25 | "type": "uint256" 26 | } 27 | ], 28 | "name": "approve", 29 | "outputs": [ 30 | { 31 | "name": "", 32 | "type": "bool" 33 | } 34 | ], 35 | "payable": false, 36 | "stateMutability": "nonpayable", 37 | "type": "function" 38 | }, 39 | { 40 | "constant": true, 41 | "inputs": [], 42 | "name": "totalSupply", 43 | "outputs": [ 44 | { 45 | "name": "", 46 | "type": "uint256" 47 | } 48 | ], 49 | "payable": false, 50 | "stateMutability": "view", 51 | "type": "function" 52 | }, 53 | { 54 | "constant": false, 55 | "inputs": [ 56 | { 57 | "name": "_from", 58 | "type": "address" 59 | }, 60 | { 61 | "name": "_to", 62 | "type": "address" 63 | }, 64 | { 65 | "name": "_value", 66 | "type": "uint256" 67 | } 68 | ], 69 | "name": "transferFrom", 70 | "outputs": [ 71 | { 72 | "name": "", 73 | "type": "bool" 74 | } 75 | ], 76 | "payable": false, 77 | "stateMutability": "nonpayable", 78 | "type": "function" 79 | }, 80 | { 81 | "constant": true, 82 | "inputs": [], 83 | "name": "decimals", 84 | "outputs": [ 85 | { 86 | "name": "", 87 | "type": "uint8" 88 | } 89 | ], 90 | "payable": false, 91 | "stateMutability": "view", 92 | "type": "function" 93 | }, 94 | { 95 | "constant": true, 96 | "inputs": [ 97 | { 98 | "name": "_owner", 99 | "type": "address" 100 | } 101 | ], 102 | "name": "balanceOf", 103 | "outputs": [ 104 | { 105 | "name": "balance", 106 | "type": "uint256" 107 | } 108 | ], 109 | "payable": false, 110 | "stateMutability": "view", 111 | "type": "function" 112 | }, 113 | { 114 | "constant": true, 115 | "inputs": [], 116 | "name": "symbol", 117 | "outputs": [ 118 | { 119 | "name": "", 120 | "type": "string" 121 | } 122 | ], 123 | "payable": false, 124 | "stateMutability": "view", 125 | "type": "function" 126 | }, 127 | { 128 | "constant": false, 129 | "inputs": [ 130 | { 131 | "name": "_to", 132 | "type": "address" 133 | }, 134 | { 135 | "name": "_value", 136 | "type": "uint256" 137 | } 138 | ], 139 | "name": "transfer", 140 | "outputs": [ 141 | { 142 | "name": "", 143 | "type": "bool" 144 | } 145 | ], 146 | "payable": false, 147 | "stateMutability": "nonpayable", 148 | "type": "function" 149 | }, 150 | { 151 | "constant": true, 152 | "inputs": [ 153 | { 154 | "name": "_owner", 155 | "type": "address" 156 | }, 157 | { 158 | "name": "_spender", 159 | "type": "address" 160 | } 161 | ], 162 | "name": "allowance", 163 | "outputs": [ 164 | { 165 | "name": "", 166 | "type": "uint256" 167 | } 168 | ], 169 | "payable": false, 170 | "stateMutability": "view", 171 | "type": "function" 172 | }, 173 | { 174 | "payable": true, 175 | "stateMutability": "payable", 176 | "type": "fallback" 177 | }, 178 | { 179 | "anonymous": false, 180 | "inputs": [ 181 | { 182 | "indexed": true, 183 | "name": "owner", 184 | "type": "address" 185 | }, 186 | { 187 | "indexed": true, 188 | "name": "spender", 189 | "type": "address" 190 | }, 191 | { 192 | "indexed": false, 193 | "name": "value", 194 | "type": "uint256" 195 | } 196 | ], 197 | "name": "Approval", 198 | "type": "event" 199 | }, 200 | { 201 | "anonymous": false, 202 | "inputs": [ 203 | { 204 | "indexed": true, 205 | "name": "from", 206 | "type": "address" 207 | }, 208 | { 209 | "indexed": true, 210 | "name": "to", 211 | "type": "address" 212 | }, 213 | { 214 | "indexed": false, 215 | "name": "value", 216 | "type": "uint256" 217 | } 218 | ], 219 | "name": "Transfer", 220 | "type": "event" 221 | } 222 | ] 223 | -------------------------------------------------------------------------------- /subgraphs/exchange/abis/ERC20NameBytes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "name", 6 | "outputs": [ 7 | { 8 | "internalType": "bytes32", 9 | "name": "", 10 | "type": "bytes32" 11 | } 12 | ], 13 | "payable": false, 14 | "stateMutability": "view", 15 | "type": "function" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /subgraphs/exchange/abis/ERC20SymbolBytes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "symbol", 6 | "outputs": [ 7 | { 8 | "internalType": "bytes32", 9 | "name": "", 10 | "type": "bytes32" 11 | } 12 | ], 13 | "payable": false, 14 | "stateMutability": "view", 15 | "type": "function" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /subgraphs/exchange/abis/Factory.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_feeToSetter", 7 | "type": "address" 8 | } 9 | ], 10 | "payable": false, 11 | "stateMutability": "nonpayable", 12 | "type": "constructor" 13 | }, 14 | { 15 | "anonymous": false, 16 | "inputs": [ 17 | { 18 | "indexed": true, 19 | "internalType": "address", 20 | "name": "token0", 21 | "type": "address" 22 | }, 23 | { 24 | "indexed": true, 25 | "internalType": "address", 26 | "name": "token1", 27 | "type": "address" 28 | }, 29 | { 30 | "indexed": false, 31 | "internalType": "address", 32 | "name": "pair", 33 | "type": "address" 34 | }, 35 | { 36 | "indexed": false, 37 | "internalType": "uint256", 38 | "name": "", 39 | "type": "uint256" 40 | } 41 | ], 42 | "name": "PairCreated", 43 | "type": "event" 44 | }, 45 | { 46 | "constant": true, 47 | "inputs": [], 48 | "name": "INIT_CODE_PAIR_HASH", 49 | "outputs": [ 50 | { 51 | "internalType": "bytes32", 52 | "name": "", 53 | "type": "bytes32" 54 | } 55 | ], 56 | "payable": false, 57 | "stateMutability": "view", 58 | "type": "function" 59 | }, 60 | { 61 | "constant": true, 62 | "inputs": [ 63 | { 64 | "internalType": "uint256", 65 | "name": "", 66 | "type": "uint256" 67 | } 68 | ], 69 | "name": "allPairs", 70 | "outputs": [ 71 | { 72 | "internalType": "address", 73 | "name": "", 74 | "type": "address" 75 | } 76 | ], 77 | "payable": false, 78 | "stateMutability": "view", 79 | "type": "function" 80 | }, 81 | { 82 | "constant": true, 83 | "inputs": [], 84 | "name": "allPairsLength", 85 | "outputs": [ 86 | { 87 | "internalType": "uint256", 88 | "name": "", 89 | "type": "uint256" 90 | } 91 | ], 92 | "payable": false, 93 | "stateMutability": "view", 94 | "type": "function" 95 | }, 96 | { 97 | "constant": false, 98 | "inputs": [ 99 | { 100 | "internalType": "address", 101 | "name": "tokenA", 102 | "type": "address" 103 | }, 104 | { 105 | "internalType": "address", 106 | "name": "tokenB", 107 | "type": "address" 108 | } 109 | ], 110 | "name": "createPair", 111 | "outputs": [ 112 | { 113 | "internalType": "address", 114 | "name": "pair", 115 | "type": "address" 116 | } 117 | ], 118 | "payable": false, 119 | "stateMutability": "nonpayable", 120 | "type": "function" 121 | }, 122 | { 123 | "constant": true, 124 | "inputs": [], 125 | "name": "feeTo", 126 | "outputs": [ 127 | { 128 | "internalType": "address", 129 | "name": "", 130 | "type": "address" 131 | } 132 | ], 133 | "payable": false, 134 | "stateMutability": "view", 135 | "type": "function" 136 | }, 137 | { 138 | "constant": true, 139 | "inputs": [], 140 | "name": "feeToSetter", 141 | "outputs": [ 142 | { 143 | "internalType": "address", 144 | "name": "", 145 | "type": "address" 146 | } 147 | ], 148 | "payable": false, 149 | "stateMutability": "view", 150 | "type": "function" 151 | }, 152 | { 153 | "constant": true, 154 | "inputs": [ 155 | { 156 | "internalType": "address", 157 | "name": "", 158 | "type": "address" 159 | }, 160 | { 161 | "internalType": "address", 162 | "name": "", 163 | "type": "address" 164 | } 165 | ], 166 | "name": "getPair", 167 | "outputs": [ 168 | { 169 | "internalType": "address", 170 | "name": "", 171 | "type": "address" 172 | } 173 | ], 174 | "payable": false, 175 | "stateMutability": "view", 176 | "type": "function" 177 | }, 178 | { 179 | "constant": false, 180 | "inputs": [ 181 | { 182 | "internalType": "address", 183 | "name": "_feeTo", 184 | "type": "address" 185 | } 186 | ], 187 | "name": "setFeeTo", 188 | "outputs": [], 189 | "payable": false, 190 | "stateMutability": "nonpayable", 191 | "type": "function" 192 | }, 193 | { 194 | "constant": false, 195 | "inputs": [ 196 | { 197 | "internalType": "address", 198 | "name": "_feeToSetter", 199 | "type": "address" 200 | } 201 | ], 202 | "name": "setFeeToSetter", 203 | "outputs": [], 204 | "payable": false, 205 | "stateMutability": "nonpayable", 206 | "type": "function" 207 | } 208 | ] 209 | -------------------------------------------------------------------------------- /subgraphs/exchange/mappings/dayUpdates.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { PairHourData } from "../generated/schema"; 3 | import { BigInt, BigDecimal, ethereum } from "@graphprotocol/graph-ts"; 4 | import { Pair, Bundle, Token, PancakeFactory, PancakeDayData, PairDayData, TokenDayData } from "../generated/schema"; 5 | import { ONE_BI, ZERO_BD, ZERO_BI, FACTORY_ADDRESS } from "./utils"; 6 | 7 | export function updatePancakeDayData(event: ethereum.Event): PancakeDayData { 8 | let pancake = PancakeFactory.load(FACTORY_ADDRESS); 9 | let timestamp = event.block.timestamp.toI32(); 10 | let dayID = timestamp / 86400; 11 | let dayStartTimestamp = dayID * 86400; 12 | 13 | let pancakeDayData = PancakeDayData.load(dayID.toString()); 14 | if (pancakeDayData === null) { 15 | pancakeDayData = new PancakeDayData(dayID.toString()); 16 | pancakeDayData.date = dayStartTimestamp; 17 | pancakeDayData.dailyVolumeUSD = ZERO_BD; 18 | pancakeDayData.dailyVolumeBNB = ZERO_BD; 19 | pancakeDayData.totalVolumeUSD = ZERO_BD; 20 | pancakeDayData.totalVolumeBNB = ZERO_BD; 21 | pancakeDayData.dailyVolumeUntracked = ZERO_BD; 22 | } 23 | pancakeDayData.totalLiquidityUSD = pancake.totalLiquidityUSD; 24 | pancakeDayData.totalLiquidityBNB = pancake.totalLiquidityBNB; 25 | pancakeDayData.totalTransactions = pancake.totalTransactions; 26 | pancakeDayData.save(); 27 | 28 | return pancakeDayData as PancakeDayData; 29 | } 30 | 31 | export function updatePairDayData(event: ethereum.Event): PairDayData { 32 | let timestamp = event.block.timestamp.toI32(); 33 | let dayID = timestamp / 86400; 34 | let dayStartTimestamp = dayID * 86400; 35 | let dayPairID = event.address.toHex().concat("-").concat(BigInt.fromI32(dayID).toString()); 36 | let pair = Pair.load(event.address.toHex()); 37 | let pairDayData = PairDayData.load(dayPairID); 38 | if (pairDayData === null) { 39 | pairDayData = new PairDayData(dayPairID); 40 | pairDayData.date = dayStartTimestamp; 41 | pairDayData.token0 = pair.token0; 42 | pairDayData.token1 = pair.token1; 43 | pairDayData.pairAddress = event.address; 44 | pairDayData.dailyVolumeToken0 = ZERO_BD; 45 | pairDayData.dailyVolumeToken1 = ZERO_BD; 46 | pairDayData.dailyVolumeUSD = ZERO_BD; 47 | pairDayData.dailyTxns = ZERO_BI; 48 | } 49 | pairDayData.totalSupply = pair.totalSupply; 50 | pairDayData.reserve0 = pair.reserve0; 51 | pairDayData.reserve1 = pair.reserve1; 52 | pairDayData.reserveUSD = pair.reserveUSD; 53 | pairDayData.dailyTxns = pairDayData.dailyTxns.plus(ONE_BI); 54 | pairDayData.save(); 55 | 56 | return pairDayData as PairDayData; 57 | } 58 | 59 | export function updatePairHourData(event: ethereum.Event): PairHourData { 60 | let timestamp = event.block.timestamp.toI32(); 61 | let hourIndex = timestamp / 3600; 62 | let hourStartUnix = hourIndex * 3600; 63 | let hourPairID = event.address.toHex().concat("-").concat(BigInt.fromI32(hourIndex).toString()); 64 | let pair = Pair.load(event.address.toHex()); 65 | let pairHourData = PairHourData.load(hourPairID); 66 | if (pairHourData === null) { 67 | pairHourData = new PairHourData(hourPairID); 68 | pairHourData.hourStartUnix = hourStartUnix; 69 | pairHourData.pair = event.address.toHex(); 70 | pairHourData.hourlyVolumeToken0 = ZERO_BD; 71 | pairHourData.hourlyVolumeToken1 = ZERO_BD; 72 | pairHourData.hourlyVolumeUSD = ZERO_BD; 73 | pairHourData.hourlyTxns = ZERO_BI; 74 | } 75 | pairHourData.totalSupply = pair.totalSupply; 76 | pairHourData.reserve0 = pair.reserve0; 77 | pairHourData.reserve1 = pair.reserve1; 78 | pairHourData.reserveUSD = pair.reserveUSD; 79 | pairHourData.hourlyTxns = pairHourData.hourlyTxns.plus(ONE_BI); 80 | pairHourData.save(); 81 | 82 | return pairHourData as PairHourData; 83 | } 84 | 85 | export function updateTokenDayData(token: Token, event: ethereum.Event): TokenDayData { 86 | let bundle = Bundle.load("1"); 87 | let timestamp = event.block.timestamp.toI32(); 88 | let dayID = timestamp / 86400; 89 | let dayStartTimestamp = dayID * 86400; 90 | let tokenDayID = token.id.toString().concat("-").concat(BigInt.fromI32(dayID).toString()); 91 | 92 | let tokenDayData = TokenDayData.load(tokenDayID); 93 | if (tokenDayData === null) { 94 | tokenDayData = new TokenDayData(tokenDayID); 95 | tokenDayData.date = dayStartTimestamp; 96 | tokenDayData.token = token.id; 97 | tokenDayData.priceUSD = token.derivedBNB.times(bundle.bnbPrice); 98 | tokenDayData.dailyVolumeToken = ZERO_BD; 99 | tokenDayData.dailyVolumeBNB = ZERO_BD; 100 | tokenDayData.dailyVolumeUSD = ZERO_BD; 101 | tokenDayData.dailyTxns = ZERO_BI; 102 | tokenDayData.totalLiquidityUSD = ZERO_BD; 103 | } 104 | tokenDayData.priceUSD = token.derivedBNB.times(bundle.bnbPrice); 105 | tokenDayData.totalLiquidityToken = token.totalLiquidity; 106 | tokenDayData.totalLiquidityBNB = token.totalLiquidity.times(token.derivedBNB as BigDecimal); 107 | tokenDayData.totalLiquidityUSD = tokenDayData.totalLiquidityBNB.times(bundle.bnbPrice); 108 | tokenDayData.dailyTxns = tokenDayData.dailyTxns.plus(ONE_BI); 109 | tokenDayData.save(); 110 | 111 | return tokenDayData as TokenDayData; 112 | } 113 | -------------------------------------------------------------------------------- /subgraphs/exchange/mappings/factory.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { PancakeFactory, Pair, Token, Bundle } from "../generated/schema"; 3 | import { Pair as PairTemplate } from "../generated/templates"; 4 | import { PairCreated } from "../generated/Factory/Factory"; 5 | import { 6 | FACTORY_ADDRESS, 7 | ZERO_BD, 8 | ZERO_BI, 9 | ONE_BI, 10 | fetchTokenSymbol, 11 | fetchTokenName, 12 | fetchTokenDecimals, 13 | } from "./utils"; 14 | 15 | export function handlePairCreated(event: PairCreated): void { 16 | let factory = PancakeFactory.load(FACTORY_ADDRESS); 17 | if (factory === null) { 18 | factory = new PancakeFactory(FACTORY_ADDRESS); 19 | factory.totalPairs = ZERO_BI; 20 | factory.totalTransactions = ZERO_BI; 21 | factory.totalVolumeBNB = ZERO_BD; 22 | factory.totalLiquidityBNB = ZERO_BD; 23 | factory.totalVolumeUSD = ZERO_BD; 24 | factory.untrackedVolumeUSD = ZERO_BD; 25 | factory.totalLiquidityUSD = ZERO_BD; 26 | 27 | let bundle = new Bundle("1"); 28 | bundle.bnbPrice = ZERO_BD; 29 | bundle.save(); 30 | } 31 | factory.totalPairs = factory.totalPairs.plus(ONE_BI); 32 | factory.save(); 33 | 34 | let token0 = Token.load(event.params.token0.toHex()); 35 | if (token0 === null) { 36 | token0 = new Token(event.params.token0.toHex()); 37 | token0.name = fetchTokenName(event.params.token0); 38 | token0.symbol = fetchTokenSymbol(event.params.token0); 39 | let decimals = fetchTokenDecimals(event.params.token0); 40 | if (decimals === null) { 41 | return; 42 | } 43 | token0.decimals = decimals; 44 | token0.derivedBNB = ZERO_BD; 45 | token0.derivedUSD = ZERO_BD; 46 | token0.tradeVolume = ZERO_BD; 47 | token0.tradeVolumeUSD = ZERO_BD; 48 | token0.untrackedVolumeUSD = ZERO_BD; 49 | token0.totalLiquidity = ZERO_BD; 50 | token0.totalTransactions = ZERO_BI; 51 | token0.save(); 52 | } 53 | 54 | let token1 = Token.load(event.params.token1.toHex()); 55 | if (token1 === null) { 56 | token1 = new Token(event.params.token1.toHex()); 57 | token1.name = fetchTokenName(event.params.token1); 58 | token1.symbol = fetchTokenSymbol(event.params.token1); 59 | let decimals = fetchTokenDecimals(event.params.token1); 60 | if (decimals === null) { 61 | return; 62 | } 63 | token1.decimals = decimals; 64 | token1.derivedBNB = ZERO_BD; 65 | token1.derivedUSD = ZERO_BD; 66 | token1.tradeVolume = ZERO_BD; 67 | token1.tradeVolumeUSD = ZERO_BD; 68 | token1.untrackedVolumeUSD = ZERO_BD; 69 | token1.totalLiquidity = ZERO_BD; 70 | token1.totalTransactions = ZERO_BI; 71 | token1.save(); 72 | } 73 | 74 | let pair = new Pair(event.params.pair.toHex()) as Pair; 75 | pair.token0 = token0.id; 76 | pair.token1 = token1.id; 77 | pair.name = token0.symbol.concat("-").concat(token1.symbol); 78 | pair.totalTransactions = ZERO_BI; 79 | pair.reserve0 = ZERO_BD; 80 | pair.reserve1 = ZERO_BD; 81 | pair.trackedReserveBNB = ZERO_BD; 82 | pair.reserveBNB = ZERO_BD; 83 | pair.reserveUSD = ZERO_BD; 84 | pair.totalSupply = ZERO_BD; 85 | pair.volumeToken0 = ZERO_BD; 86 | pair.volumeToken1 = ZERO_BD; 87 | pair.volumeUSD = ZERO_BD; 88 | pair.untrackedVolumeUSD = ZERO_BD; 89 | pair.token0Price = ZERO_BD; 90 | pair.token1Price = ZERO_BD; 91 | pair.block = event.block.number; 92 | pair.timestamp = event.block.timestamp; 93 | pair.save(); 94 | 95 | PairTemplate.create(event.params.pair); 96 | } 97 | -------------------------------------------------------------------------------- /subgraphs/exchange/mappings/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigInt, BigDecimal, Address } from "@graphprotocol/graph-ts"; 3 | import { ERC20 } from "../../generated/Factory/ERC20"; 4 | import { ERC20NameBytes } from "../../generated/Factory/ERC20NameBytes"; 5 | import { ERC20SymbolBytes } from "../../generated/Factory/ERC20SymbolBytes"; 6 | import { Factory as FactoryContract } from "../../generated/templates/Pair/Factory"; 7 | 8 | export let ADDRESS_ZERO = "0x0000000000000000000000000000000000000000"; 9 | export let FACTORY_ADDRESS = "0xca143ce32fe78f1f7019d7d551a6402fc5350c73"; 10 | 11 | export let ZERO_BI = BigInt.fromI32(0); 12 | export let ONE_BI = BigInt.fromI32(1); 13 | export let ZERO_BD = BigDecimal.fromString("0"); 14 | export let ONE_BD = BigDecimal.fromString("1"); 15 | export let BI_18 = BigInt.fromI32(18); 16 | 17 | export let factoryContract = FactoryContract.bind(Address.fromString(FACTORY_ADDRESS)); 18 | 19 | export function exponentToBigDecimal(decimals: BigInt): BigDecimal { 20 | let bd = BigDecimal.fromString("1"); 21 | for (let i = ZERO_BI; i.lt(decimals as BigInt); i = i.plus(ONE_BI)) { 22 | bd = bd.times(BigDecimal.fromString("10")); 23 | } 24 | return bd; 25 | } 26 | 27 | export function convertTokenToDecimal(tokenAmount: BigInt, exchangeDecimals: BigInt): BigDecimal { 28 | if (exchangeDecimals == ZERO_BI) { 29 | return tokenAmount.toBigDecimal(); 30 | } 31 | return tokenAmount.toBigDecimal().div(exponentToBigDecimal(exchangeDecimals)); 32 | } 33 | 34 | export function isNullBnbValue(value: string): boolean { 35 | return value == "0x0000000000000000000000000000000000000000000000000000000000000001"; 36 | } 37 | 38 | export function fetchTokenSymbol(tokenAddress: Address): string { 39 | let contract = ERC20.bind(tokenAddress); 40 | let contractSymbolBytes = ERC20SymbolBytes.bind(tokenAddress); 41 | 42 | let symbolValue = "unknown"; 43 | let symbolResult = contract.try_symbol(); 44 | if (symbolResult.reverted) { 45 | let symbolResultBytes = contractSymbolBytes.try_symbol(); 46 | if (!symbolResultBytes.reverted) { 47 | if (!isNullBnbValue(symbolResultBytes.value.toHex())) { 48 | symbolValue = symbolResultBytes.value.toString(); 49 | } 50 | } 51 | } else { 52 | symbolValue = symbolResult.value; 53 | } 54 | return symbolValue; 55 | } 56 | 57 | export function fetchTokenName(tokenAddress: Address): string { 58 | let contract = ERC20.bind(tokenAddress); 59 | let contractNameBytes = ERC20NameBytes.bind(tokenAddress); 60 | 61 | let nameValue = "unknown"; 62 | let nameResult = contract.try_name(); 63 | if (nameResult.reverted) { 64 | let nameResultBytes = contractNameBytes.try_name(); 65 | if (!nameResultBytes.reverted) { 66 | if (!isNullBnbValue(nameResultBytes.value.toHex())) { 67 | nameValue = nameResultBytes.value.toString(); 68 | } 69 | } 70 | } else { 71 | nameValue = nameResult.value; 72 | } 73 | return nameValue; 74 | } 75 | 76 | export function fetchTokenDecimals(tokenAddress: Address): BigInt { 77 | let contract = ERC20.bind(tokenAddress); 78 | let decimalValue = null; 79 | let decimalResult = contract.try_decimals(); 80 | if (!decimalResult.reverted) { 81 | decimalValue = decimalResult.value; 82 | } 83 | return BigInt.fromI32(decimalValue as i32); 84 | } 85 | -------------------------------------------------------------------------------- /subgraphs/exchange/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "exchange", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/exchange subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/exchange/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: PancakeSwap is a decentralized protocol for automated token exchange on Binance Smart Chain. 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: Factory 9 | network: bsc 10 | source: 11 | address: '0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73' 12 | abi: Factory 13 | startBlock: 6809737 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/factory.ts 19 | entities: 20 | - Pair 21 | - Token 22 | abis: 23 | - name: Factory 24 | file: ./abis/Factory.json 25 | - name: ERC20 26 | file: ./abis/ERC20.json 27 | - name: ERC20NameBytes 28 | file: ./abis/ERC20NameBytes.json 29 | - name: ERC20SymbolBytes 30 | file: ./abis/ERC20SymbolBytes.json 31 | eventHandlers: 32 | - event: PairCreated(indexed address,indexed address,address,uint256) 33 | handler: handlePairCreated 34 | templates: 35 | - kind: ethereum/contract 36 | name: Pair 37 | network: bsc 38 | source: 39 | abi: Pair 40 | mapping: 41 | kind: ethereum/events 42 | apiVersion: 0.0.4 43 | language: wasm/assemblyscript 44 | file: ./mappings/core.ts 45 | entities: 46 | - Pair 47 | - Token 48 | abis: 49 | - name: Factory 50 | file: ./abis/Factory.json 51 | - name: Pair 52 | file: ./abis/Pair.json 53 | eventHandlers: 54 | - event: Mint(indexed address,uint256,uint256) 55 | handler: handleMint 56 | - event: Burn(indexed address,uint256,uint256,indexed address) 57 | handler: handleBurn 58 | - event: Swap(indexed address,uint256,uint256,uint256,uint256,indexed address) 59 | handler: handleSwap 60 | - event: Transfer(indexed address,indexed address,uint256) 61 | handler: handleTransfer 62 | - event: Sync(uint112,uint112) 63 | handler: handleSync 64 | -------------------------------------------------------------------------------- /subgraphs/farm-auctions/mappings/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigDecimal, BigInt } from "@graphprotocol/graph-ts"; 3 | import { Auction, Bidder } from "../generated/schema"; 4 | import { 5 | AuctionBid, 6 | AuctionClose, 7 | AuctionStart, 8 | WhitelistAdd, 9 | WhitelistRemove, 10 | } from "../generated/FarmAuction/FarmAuction"; 11 | import { toBigDecimal } from "./utils"; 12 | 13 | // BigNumber-like references 14 | let ZERO_BI = BigInt.fromI32(0); 15 | let ONE_BI = BigInt.fromI32(1); 16 | let ZERO_BD = BigDecimal.fromString("0"); 17 | 18 | /** 19 | * Whitelisting service 20 | */ 21 | 22 | export function handleWhitelistAdd(event: WhitelistAdd): void { 23 | let bidder = Bidder.load(event.params.account.toHex()); 24 | if (bidder === null) { 25 | bidder = new Bidder(event.params.account.toHex()); 26 | bidder.isWhitelisted = true; 27 | bidder.totalBids = ZERO_BI; 28 | bidder.totalCake = ZERO_BD; 29 | bidder.block = event.block.number; 30 | bidder.timestamp = event.block.timestamp; 31 | bidder.save(); 32 | } 33 | bidder.isWhitelisted = true; 34 | bidder.save(); 35 | } 36 | 37 | export function handleWhitelistRemove(event: WhitelistRemove): void { 38 | let bidder = Bidder.load(event.params.account.toHex()); 39 | if (bidder === null) { 40 | bidder = new Bidder(event.params.account.toHex()); 41 | bidder.isWhitelisted = false; 42 | bidder.totalBids = ZERO_BI; 43 | bidder.totalCake = ZERO_BD; 44 | bidder.block = event.block.number; 45 | bidder.timestamp = event.block.timestamp; 46 | bidder.save(); 47 | } 48 | bidder.isWhitelisted = false; 49 | bidder.save(); 50 | } 51 | 52 | /** 53 | * Auction service 54 | */ 55 | 56 | export function handleAuctionStart(event: AuctionStart): void { 57 | let auction = new Auction(event.params.auctionId.toString()); 58 | auction.totalBids = ZERO_BI; 59 | auction.totalCake = ZERO_BD; 60 | auction.status = "Open"; 61 | auction.startBlock = event.params.startBlock; 62 | auction.endBlock = event.params.endBlock; 63 | auction.initialBidAmount = toBigDecimal(event.params.initialBidAmount); 64 | auction.leaderboard = event.params.leaderboard; 65 | auction.leaderboardThreshold = ZERO_BD; 66 | auction.save(); 67 | } 68 | 69 | export function handleAuctionClose(event: AuctionClose): void { 70 | let auction = Auction.load(event.params.auctionId.toString()); 71 | if (auction !== null) { 72 | auction.status = "Close"; 73 | auction.leaderboardThreshold = toBigDecimal(event.params.participationLimit); 74 | auction.save(); 75 | } 76 | } 77 | 78 | export function handleAuctionBid(event: AuctionBid): void { 79 | let auction = Auction.load(event.params.auctionId.toString()); 80 | if (auction !== null) { 81 | auction.totalBids = auction.totalBids.plus(ONE_BI); 82 | auction.totalCake = auction.totalCake.plus(toBigDecimal(event.params.amount)); 83 | auction.save(); 84 | } 85 | 86 | let bidder = Bidder.load(event.params.account.toHex()); 87 | if (bidder !== null) { 88 | bidder.totalBids = bidder.totalBids.plus(ONE_BI); 89 | bidder.totalCake = bidder.totalCake.plus(toBigDecimal(event.params.amount)); 90 | bidder.save(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /subgraphs/farm-auctions/mappings/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigDecimal, BigInt } from "@graphprotocol/graph-ts"; 3 | 4 | export function toBigDecimal(quantity: BigInt, decimals: i32 = 18): BigDecimal { 5 | return quantity.divDecimal( 6 | BigInt.fromI32(10) 7 | .pow(decimals as u8) 8 | .toBigDecimal() 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /subgraphs/farm-auctions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "farm-auctions", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/farm-auctions subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/farm-auctions/schema.graphql: -------------------------------------------------------------------------------- 1 | enum Status { 2 | Pending 3 | Open 4 | Close 5 | } 6 | 7 | """ 8 | Auctions 9 | """ 10 | type Auction @entity { 11 | "ID" 12 | id: ID! 13 | 14 | "Status" 15 | status: Status! 16 | 17 | "Total of Bids" 18 | totalBids: BigInt! 19 | "Total of Cake" 20 | totalCake: BigDecimal! 21 | 22 | startBlock: BigInt! 23 | endBlock: BigInt! 24 | 25 | initialBidAmount: BigDecimal! 26 | 27 | leaderboard: BigInt! 28 | leaderboardThreshold: BigDecimal! 29 | } 30 | 31 | """ 32 | Bidders 33 | """ 34 | type Bidder @entity { 35 | "ID (address)" 36 | id: ID! 37 | 38 | "Whitelist status" 39 | isWhitelisted: Boolean! 40 | 41 | "Total of Bids" 42 | totalBids: BigInt! 43 | 44 | "Total of Cake" 45 | totalCake: BigDecimal! 46 | 47 | "Block number" 48 | block: BigInt! 49 | "Block timestamp" 50 | timestamp: BigInt! 51 | } 52 | -------------------------------------------------------------------------------- /subgraphs/farm-auctions/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Pancake Farm Auction 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: FarmAuction 9 | network: bsc 10 | source: 11 | address: '0xb92Ab7c1edcb273AbA24b0656cEb3681654805D2' 12 | abi: FarmAuction 13 | startBlock: 9678443 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/index.ts 19 | entities: 20 | - Auction 21 | - Bidder 22 | abis: 23 | - name: FarmAuction 24 | file: ./abis/FarmAuction.json 25 | eventHandlers: 26 | - event: WhitelistAdd(indexed address) 27 | handler: handleWhitelistAdd 28 | - event: WhitelistRemove(indexed address) 29 | handler: handleWhitelistRemove 30 | - event: AuctionStart(indexed uint256,uint256,uint256,uint256,uint256) 31 | handler: handleAuctionStart 32 | - event: AuctionClose(indexed uint256,uint256,uint256) 33 | handler: handleAuctionClose 34 | - event: AuctionBid(indexed uint256,indexed address,uint256) 35 | handler: handleAuctionBid 36 | -------------------------------------------------------------------------------- /subgraphs/lottery/mappings/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigDecimal, BigInt, Bytes, log } from "@graphprotocol/graph-ts"; 3 | import { concat } from "@graphprotocol/graph-ts/helper-functions"; 4 | import { Lottery, Round, User } from "../generated/schema"; 5 | import { 6 | LotteryClose, 7 | LotteryNumberDrawn, 8 | LotteryOpen, 9 | TicketsClaim, 10 | TicketsPurchase, 11 | } from "../generated/Lottery/Lottery"; 12 | import { toBigDecimal } from "./utils"; 13 | 14 | // BigNumber-like references 15 | let ZERO_BI = BigInt.fromI32(0); 16 | let ONE_BI = BigInt.fromI32(1); 17 | let ZERO_BD = BigDecimal.fromString("0"); 18 | 19 | export function handleLotteryOpen(event: LotteryOpen): void { 20 | let lottery = new Lottery(event.params.lotteryId.toString()); 21 | lottery.totalUsers = ZERO_BI; 22 | lottery.totalTickets = ZERO_BI; 23 | lottery.status = "Open"; 24 | lottery.startTime = event.params.startTime; 25 | lottery.endTime = event.params.endTime; 26 | lottery.ticketPrice = toBigDecimal(event.params.priceTicketInCake); 27 | lottery.firstTicket = event.params.firstTicketId; 28 | lottery.block = event.block.number; 29 | lottery.timestamp = event.block.timestamp; 30 | lottery.save(); 31 | } 32 | 33 | export function handleLotteryClose(event: LotteryClose): void { 34 | let lottery = new Lottery(event.params.lotteryId.toString()); 35 | if (lottery !== null) { 36 | lottery.status = "Close"; 37 | lottery.lastTicket = event.params.firstTicketIdNextLottery; 38 | lottery.save(); 39 | } 40 | } 41 | 42 | export function handleLotteryNumberDrawn(event: LotteryNumberDrawn): void { 43 | let lottery = new Lottery(event.params.lotteryId.toString()); 44 | if (lottery !== null) { 45 | lottery.status = "Claimable"; 46 | lottery.finalNumber = event.params.finalNumber; 47 | lottery.winningTickets = event.params.countWinningTickets; 48 | lottery.claimedTickets = ZERO_BI; 49 | lottery.save(); 50 | } 51 | } 52 | 53 | export function handleTicketsPurchase(event: TicketsPurchase): void { 54 | let lottery = Lottery.load(event.params.lotteryId.toString()); 55 | if (lottery === null) { 56 | log.warning("Trying to purchase tickets for an unknown lottery - #{}", [event.params.lotteryId.toString()]); 57 | } 58 | lottery.totalTickets = lottery.totalTickets.plus(event.params.numberTickets); 59 | lottery.save(); 60 | 61 | let user = User.load(event.params.buyer.toHex()); 62 | if (user === null) { 63 | user = new User(event.params.buyer.toHex()); 64 | user.totalRounds = ZERO_BI; 65 | user.totalTickets = ZERO_BI; 66 | user.totalCake = ZERO_BD; 67 | user.block = event.block.number; 68 | user.timestamp = event.block.timestamp; 69 | user.save(); 70 | } 71 | user.totalTickets = user.totalTickets.plus(event.params.numberTickets); 72 | user.totalCake = user.totalCake.plus(event.params.numberTickets.toBigDecimal().times(lottery.ticketPrice)); 73 | user.save(); 74 | 75 | let roundId = concat( 76 | Bytes.fromHexString(event.params.buyer.toHex()), 77 | Bytes.fromUTF8(event.params.lotteryId.toString()) 78 | ).toHex(); 79 | let round = Round.load(roundId); 80 | if (round === null) { 81 | round = new Round(roundId); 82 | round.lottery = event.params.lotteryId.toString(); 83 | round.user = event.params.buyer.toHex(); 84 | round.totalTickets = ZERO_BI; 85 | round.block = event.block.number; 86 | round.timestamp = event.block.timestamp; 87 | round.save(); 88 | 89 | user.totalRounds = user.totalRounds.plus(ONE_BI); 90 | user.save(); 91 | 92 | lottery.totalUsers = lottery.totalUsers.plus(ONE_BI); 93 | lottery.save(); 94 | } 95 | round.totalTickets = round.totalTickets.plus(event.params.numberTickets); 96 | round.save(); 97 | } 98 | 99 | export function handleTicketsClaim(event: TicketsClaim): void { 100 | let lottery = Lottery.load(event.params.lotteryId.toString()); 101 | if (lottery !== null) { 102 | lottery.claimedTickets = lottery.claimedTickets.plus(event.params.numberTickets); 103 | lottery.save(); 104 | } 105 | 106 | let user = User.load(event.params.claimer.toHex()); 107 | if (user !== null) { 108 | user.totalCake = user.totalCake.plus(toBigDecimal(event.params.amount)); 109 | user.save(); 110 | } 111 | 112 | let roundId = concat( 113 | Bytes.fromHexString(event.params.claimer.toHex()), 114 | Bytes.fromUTF8(event.params.lotteryId.toString()) 115 | ).toHex(); 116 | let round = Round.load(roundId); 117 | if (round !== null) { 118 | round.claimed = true; 119 | round.save(); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /subgraphs/lottery/mappings/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigDecimal, BigInt } from "@graphprotocol/graph-ts"; 3 | 4 | export function toBigDecimal(quantity: BigInt, decimals: i32 = 18): BigDecimal { 5 | return quantity.divDecimal( 6 | BigInt.fromI32(10) 7 | .pow(decimals as u8) 8 | .toBigDecimal() 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /subgraphs/lottery/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lottery", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/lottery subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/lottery/schema.graphql: -------------------------------------------------------------------------------- 1 | enum Status { 2 | Pending 3 | Open 4 | Close 5 | Claimable 6 | } 7 | 8 | """ 9 | PancakeSwap Lottery 10 | """ 11 | type Lottery @entity { 12 | "ID" 13 | id: ID! 14 | 15 | totalUsers: BigInt! 16 | totalTickets: BigInt! 17 | 18 | status: Status! 19 | 20 | finalNumber: BigInt 21 | winningTickets: BigInt 22 | claimedTickets: BigInt 23 | 24 | startTime: BigInt! 25 | endTime: BigInt! 26 | 27 | ticketPrice: BigDecimal! 28 | firstTicket: BigInt! 29 | lastTicket: BigInt 30 | 31 | "Block number" 32 | block: BigInt! 33 | "Block timestamp" 34 | timestamp: BigInt! 35 | } 36 | 37 | type User @entity { 38 | "ID" 39 | id: ID! 40 | 41 | totalRounds: BigInt! 42 | 43 | totalTickets: BigInt! 44 | rounds: [Round!]! @derivedFrom(field: "user") 45 | 46 | totalCake: BigDecimal! 47 | 48 | "Block number" 49 | block: BigInt! 50 | "Block timestamp" 51 | timestamp: BigInt! 52 | } 53 | 54 | type Round @entity { 55 | "ID" 56 | id: ID! 57 | 58 | lottery: Lottery! 59 | user: User! 60 | 61 | claimed: Boolean 62 | totalTickets: BigInt! 63 | 64 | "Block number" 65 | block: BigInt! 66 | "Block timestamp" 67 | timestamp: BigInt! 68 | } 69 | -------------------------------------------------------------------------------- /subgraphs/lottery/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: PancakeSwap Lottery 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: Lottery 9 | network: bsc 10 | source: 11 | address: '0x5aF6D33DE2ccEC94efb1bDF8f92Bd58085432d2c' 12 | abi: Lottery 13 | startBlock: 8796011 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/index.ts 19 | entities: 20 | - Lottery 21 | - User 22 | - Round 23 | abis: 24 | - name: Lottery 25 | file: ./abis/Lottery.json 26 | eventHandlers: 27 | - event: LotteryOpen(indexed uint256,uint256,uint256,uint256,uint256,uint256) 28 | handler: handleLotteryOpen 29 | - event: LotteryClose(indexed uint256,uint256) 30 | handler: handleLotteryClose 31 | - event: LotteryNumberDrawn(indexed uint256,uint256,uint256) 32 | handler: handleLotteryNumberDrawn 33 | - event: TicketsPurchase(indexed address,indexed uint256,uint256) 34 | handler: handleTicketsPurchase 35 | - event: TicketsClaim(indexed address,uint256,indexed uint256,uint256) 36 | handler: handleTicketsClaim 37 | -------------------------------------------------------------------------------- /subgraphs/masterchef-v2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "masterchef-v2", 3 | "description": "PancakeSwap MasterChef V2 Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/masterchef-v2 subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/masterchef-v2/schema.graphql: -------------------------------------------------------------------------------- 1 | type MasterChef @entity { 2 | # Contract address 3 | id: ID! 4 | 5 | totalRegularAllocPoint: BigInt! 6 | totalSpecialAllocPoint: BigInt! 7 | cakeRateToBurn: BigInt! 8 | cakeRateToRegularFarm: BigInt! 9 | cakeRateToSpecialFarm: BigInt! 10 | 11 | pools: [Pool!] @derivedFrom(field: "masterChef") 12 | poolCount: BigInt! 13 | 14 | timestamp: BigInt! 15 | block: BigInt! 16 | } 17 | 18 | type Pool @entity { 19 | # Index of pool in poolInfo on MasterChef contract 20 | id: ID! 21 | masterChef: MasterChef! 22 | pair: Bytes! 23 | 24 | allocPoint: BigInt! 25 | lastRewardBlock: BigInt! 26 | accCakePerShare: BigInt! 27 | totalBoostedShare: BigInt! 28 | isRegular: Boolean 29 | 30 | slpBalance: BigInt! 31 | 32 | users: [User!]! @derivedFrom(field: "pool") 33 | # total user include deposit and withdraw all 34 | totalUsersCount: BigInt! 35 | userCount: BigInt! 36 | 37 | timestamp: BigInt! 38 | block: BigInt! 39 | } 40 | 41 | type User @entity { 42 | # Pool id concatenated with user address 43 | id: ID! 44 | 45 | address: Bytes! 46 | pool: Pool! 47 | boostMultiplier: BigInt! 48 | 49 | amount: BigInt! 50 | rewardDebt: BigInt! 51 | 52 | timestamp: BigInt! 53 | block: BigInt! 54 | } 55 | -------------------------------------------------------------------------------- /subgraphs/masterchef-v2/src/entities/master-chef.ts: -------------------------------------------------------------------------------- 1 | import { BigInt, dataSource, ethereum } from "@graphprotocol/graph-ts"; 2 | import { MasterChef } from "../../generated/schema"; 3 | import { BI_ZERO } from "../utils"; 4 | 5 | export function getOrCreateMasterChef(block: ethereum.Block): MasterChef { 6 | let masterChef = MasterChef.load(dataSource.address().toHex()); 7 | 8 | if (masterChef === null) { 9 | masterChef = new MasterChef(dataSource.address().toHex()); 10 | masterChef.totalRegularAllocPoint = BI_ZERO; 11 | masterChef.totalSpecialAllocPoint = BI_ZERO; 12 | masterChef.cakeRateToBurn = BigInt.fromString("750000000000"); 13 | masterChef.cakeRateToRegularFarm = BigInt.fromString("100000000000"); 14 | masterChef.cakeRateToSpecialFarm = BigInt.fromString("150000000000"); 15 | masterChef.poolCount = BI_ZERO; 16 | } 17 | 18 | masterChef.timestamp = block.timestamp; 19 | masterChef.block = block.number; 20 | masterChef.save(); 21 | 22 | return masterChef as MasterChef; 23 | } 24 | -------------------------------------------------------------------------------- /subgraphs/masterchef-v2/src/entities/pool.ts: -------------------------------------------------------------------------------- 1 | import { BigInt, ethereum } from "@graphprotocol/graph-ts"; 2 | import { Pool } from "../../generated/schema"; 3 | import { ADDRESS_ZERO, BI_ZERO } from "../utils"; 4 | import { getOrCreateMasterChef } from "./master-chef"; 5 | 6 | export function getOrCreatePool(pid: BigInt, block: ethereum.Block): Pool { 7 | const masterChef = getOrCreateMasterChef(block); 8 | 9 | let pool = Pool.load(pid.toString()); 10 | 11 | if (pool === null) { 12 | pool = new Pool(pid.toString()); 13 | pool.masterChef = masterChef.id; 14 | pool.pair = ADDRESS_ZERO; 15 | pool.allocPoint = BI_ZERO; 16 | pool.lastRewardBlock = BI_ZERO; 17 | pool.accCakePerShare = BI_ZERO; 18 | pool.slpBalance = BI_ZERO; 19 | pool.userCount = BI_ZERO; 20 | pool.totalUsersCount = BI_ZERO; 21 | pool.totalBoostedShare = BI_ZERO; 22 | } 23 | 24 | pool.timestamp = block.timestamp; 25 | pool.block = block.number; 26 | pool.lastRewardBlock = block.number; 27 | pool.save(); 28 | 29 | return pool as Pool; 30 | } 31 | -------------------------------------------------------------------------------- /subgraphs/masterchef-v2/src/entities/user.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unused-vars */ 2 | import { Pool, User } from "../../generated/schema"; 3 | import { BigInt, Address, ethereum } from "@graphprotocol/graph-ts"; 4 | import { getOrCreateMasterChef } from "./master-chef"; 5 | import { getOrCreatePool } from "./pool"; 6 | import { BI_ZERO, BI_ONE, BOOST_PRECISION } from "../utils"; 7 | 8 | export function getOrCreateUser(address: Address, pool: Pool, block: ethereum.Block): User { 9 | const masterChef = getOrCreateMasterChef(block); 10 | 11 | const uid = address.toHex(); 12 | const id = pool.id.concat("-").concat(uid); 13 | let user = User.load(id); 14 | 15 | if (user === null) { 16 | user = new User(id); 17 | user.address = address; 18 | user.pool = pool.id; 19 | user.amount = BI_ZERO; 20 | user.rewardDebt = BI_ZERO; 21 | user.boostMultiplier = BOOST_PRECISION; 22 | 23 | pool.userCount = pool.userCount.plus(BI_ONE); 24 | pool.totalUsersCount = pool.totalUsersCount.plus(BI_ONE); 25 | pool.save(); 26 | } 27 | 28 | user.timestamp = block.timestamp; 29 | user.block = block.number; 30 | user.save(); 31 | 32 | return user as User; 33 | } 34 | 35 | export function getBoostMultiplier(user: User): BigInt { 36 | return user.boostMultiplier.gt(BOOST_PRECISION) ? user.boostMultiplier : BOOST_PRECISION; 37 | } 38 | -------------------------------------------------------------------------------- /subgraphs/masterchef-v2/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { Address, BigInt } from "@graphprotocol/graph-ts"; 2 | 3 | export const BI_ZERO = BigInt.fromI32(0); 4 | export const BI_ONE = BigInt.fromI32(1); 5 | 6 | export const ADDRESS_ZERO = Address.fromString("0x0000000000000000000000000000000000000000"); 7 | export const ACC_CAKE_PRECISION = BigInt.fromString("1000000000000"); 8 | 9 | export const BOOST_PRECISION = BigInt.fromString("1000000000000"); 10 | -------------------------------------------------------------------------------- /subgraphs/masterchef-v2/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.3 2 | description: MasterChefV2 3 | repository: https://github.com/pancakeswap/pancakeswapswap-subgraph 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: MasterChefV2 9 | network: bsc 10 | source: 11 | address: "0xa5f8C5Dbd5F286960b9d90548680aE5ebFf07652" 12 | abi: MasterChefV2 13 | startBlock: 17047980 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./src/mappings/masterchefV2.ts 19 | entities: 20 | - MasterChefV2 21 | - Pool 22 | - User 23 | abis: 24 | - name: MasterChefV2 25 | file: ./abis/MasterChefV2.json 26 | eventHandlers: 27 | - event: Deposit(indexed address,indexed uint256,uint256) 28 | handler: handleDeposit 29 | - event: Withdraw(indexed address,indexed uint256,uint256) 30 | handler: handleWithdraw 31 | - event: EmergencyWithdraw(indexed address,indexed uint256,uint256) 32 | handler: handleEmergencyWithdraw 33 | - event: AddPool(indexed uint256,uint256,indexed address,bool) 34 | handler: handleAddPool 35 | - event: SetPool(indexed uint256,uint256) 36 | handler: handleSetPool 37 | - event: UpdatePool(indexed uint256,uint256,uint256,uint256) 38 | handler: handleUpdatePool 39 | - event: UpdateBoostMultiplier(indexed address,uint256,uint256,uint256) 40 | handler: handleUpdateBoostMultiplier 41 | - event: UpdateCakeRate(uint256,uint256,uint256) 42 | handler: handleUpdateCakeRate 43 | -------------------------------------------------------------------------------- /subgraphs/nft-market/mappings/utils/dayUpdates.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigInt, BigDecimal, ethereum } from "@graphprotocol/graph-ts"; 3 | import { CollectionDayData, MarketPlaceDayData } from "../../generated/schema"; 4 | 5 | // BigNumber-like references 6 | let ZERO_BI = BigInt.fromI32(0); 7 | let ONE_BI = BigInt.fromI32(1); 8 | let ZERO_BD = BigDecimal.fromString("0"); 9 | 10 | export function updateMarketPlaceDayData(newVolumeInBNB: BigDecimal, event: ethereum.Event): void { 11 | let timestamp = event.block.timestamp.toI32(); 12 | let dayID = timestamp / 86400; 13 | let dayStartTimestamp = dayID * 86400; 14 | 15 | let marketPlaceDayData = MarketPlaceDayData.load(dayID.toString()); 16 | if (marketPlaceDayData === null) { 17 | marketPlaceDayData = new MarketPlaceDayData(dayID.toString()); 18 | marketPlaceDayData.date = dayStartTimestamp; 19 | marketPlaceDayData.dailyVolumeBNB = ZERO_BD; 20 | marketPlaceDayData.dailyTrades = ZERO_BI; 21 | } 22 | marketPlaceDayData.dailyVolumeBNB = marketPlaceDayData.dailyVolumeBNB.plus(newVolumeInBNB); 23 | marketPlaceDayData.dailyTrades = marketPlaceDayData.dailyTrades.plus(ONE_BI); 24 | marketPlaceDayData.save(); 25 | } 26 | 27 | export function updateCollectionDayData(collection: Address, newVolumeInBNB: BigDecimal, event: ethereum.Event): void { 28 | let timestamp = event.block.timestamp.toI32(); 29 | let dayID = timestamp / 86400; 30 | let dayStartTimestamp = dayID * 86400; 31 | let ID = dayID.toString() + "-" + collection.toHex(); 32 | 33 | let collectionDayData = CollectionDayData.load(ID); 34 | if (collectionDayData === null) { 35 | collectionDayData = new CollectionDayData(ID); 36 | collectionDayData.date = dayStartTimestamp; 37 | collectionDayData.collection = collection.toHex(); 38 | collectionDayData.dailyVolumeBNB = ZERO_BD; 39 | collectionDayData.dailyTrades = ZERO_BI; 40 | } 41 | collectionDayData.dailyVolumeBNB = collectionDayData.dailyVolumeBNB.plus(newVolumeInBNB); 42 | collectionDayData.dailyTrades = collectionDayData.dailyTrades.plus(ONE_BI); 43 | collectionDayData.save(); 44 | } 45 | -------------------------------------------------------------------------------- /subgraphs/nft-market/mappings/utils/erc721.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigInt } from "@graphprotocol/graph-ts"; 3 | import { IERC721 } from "../../generated/ERC721NFTMarketV1/IERC721"; 4 | import { PancakeBunnies } from "../../generated/ERC721NFTMarketV1/PancakeBunnies"; 5 | 6 | export function fetchName(collectionAddress: Address): string { 7 | let contract = IERC721.bind(collectionAddress); 8 | 9 | let nameResult = contract.try_name(); 10 | if (!nameResult.reverted) { 11 | return nameResult.value; 12 | } 13 | 14 | return "unknown"; 15 | } 16 | 17 | export function fetchSymbol(collectionAddress: Address): string { 18 | let contract = IERC721.bind(collectionAddress); 19 | 20 | let symbolResult = contract.try_symbol(); 21 | if (!symbolResult.reverted) { 22 | return symbolResult.value; 23 | } 24 | 25 | return "unknown"; 26 | } 27 | 28 | export function fetchTokenURI(collectionAddress: Address, tokenId: BigInt): string | null { 29 | let contract = IERC721.bind(collectionAddress); 30 | 31 | let tokenURIResult = contract.try_tokenURI(tokenId); 32 | if (!tokenURIResult.reverted) { 33 | return tokenURIResult.value; 34 | } 35 | 36 | return null; 37 | } 38 | 39 | export function fetchBunnyId(collectionAddress: Address, tokenId: BigInt): BigInt | null { 40 | let contract = PancakeBunnies.bind(collectionAddress); 41 | 42 | let bunnyIdResult = contract.try_getBunnyId(tokenId); 43 | if (!bunnyIdResult.reverted) { 44 | return BigInt.fromI32(bunnyIdResult.value); 45 | } 46 | 47 | return null; 48 | } 49 | -------------------------------------------------------------------------------- /subgraphs/nft-market/mappings/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigDecimal, BigInt } from "@graphprotocol/graph-ts"; 3 | 4 | export function toBigDecimal(quantity: BigInt, decimals: i32 = 18): BigDecimal { 5 | return quantity.divDecimal( 6 | BigInt.fromI32(10) 7 | .pow(decimals as u8) 8 | .toBigDecimal() 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /subgraphs/nft-market/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nft-market", 3 | "description": "PancakeSwap NFT Market Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/nft-market subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/nft-market/schema.graphql: -------------------------------------------------------------------------------- 1 | enum OrderType { 2 | New 3 | Modify 4 | Cancel 5 | } 6 | 7 | type Collection @entity { 8 | "ID (address)" 9 | id: ID! 10 | 11 | "Name" 12 | name: String! 13 | 14 | "Symbol" 15 | symbol: String! 16 | 17 | "Is active" 18 | active: Boolean! 19 | 20 | "Total of Trades" 21 | totalTrades: BigInt! 22 | 23 | "Total volume of collection traded (in BNB)" 24 | totalVolumeBNB: BigDecimal! 25 | 26 | "Number tokens listed" 27 | numberTokensListed: BigInt! 28 | 29 | "List of NFTs" 30 | nfts: [NFT!]! @derivedFrom(field: "collection") 31 | 32 | "Creator address" 33 | creatorAddress: Bytes! 34 | 35 | "Trading fee" 36 | tradingFee: BigDecimal! 37 | 38 | "Creator fee" 39 | creatorFee: BigDecimal! 40 | 41 | "Whitelist checker" 42 | whitelistChecker: Bytes! 43 | 44 | "Day history" 45 | dayData: [CollectionDayData!]! @derivedFrom(field: "collection") 46 | } 47 | 48 | type NFT @entity { 49 | "CollectionAddress + tokenId" 50 | id: ID! 51 | 52 | "tokenId" 53 | tokenId: BigInt! 54 | 55 | "otherId" 56 | otherId: BigInt 57 | 58 | "Collection address" 59 | collection: Collection! 60 | 61 | "Metadata url" 62 | metadataUrl: String 63 | 64 | "Updated at" 65 | updatedAt: BigInt! 66 | 67 | "Current ask price" 68 | currentAskPrice: BigDecimal! 69 | 70 | "Current seller" 71 | currentSeller: String! 72 | 73 | "Latest traded price in BNB" 74 | latestTradedPriceInBNB: BigDecimal! 75 | 76 | "Total volume traded (in BNB)" 77 | tradeVolumeBNB: BigDecimal! 78 | 79 | "Number of unique trades" 80 | totalTrades: BigInt! 81 | 82 | "Transaction history" 83 | transactionHistory: [Transaction!]! @derivedFrom(field: "nft") 84 | 85 | "Ask history" 86 | askHistory: [AskOrder!]! @derivedFrom(field: "nft") 87 | 88 | "isTradable" 89 | isTradable: Boolean! 90 | } 91 | 92 | type User @entity { 93 | "User address" 94 | id: ID! 95 | 96 | "Number of tokens currently listed" 97 | numberTokensListed: BigInt! 98 | 99 | "Number of tokens purchased" 100 | numberTokensPurchased: BigInt! 101 | 102 | "Number of tokens sold" 103 | numberTokensSold: BigInt! 104 | 105 | "Volume of tokens purchased (in BNB)" 106 | totalVolumeInBNBTokensPurchased: BigDecimal! 107 | 108 | "Volume of tokens sold (in BNB)" 109 | totalVolumeInBNBTokensSold: BigDecimal! 110 | 111 | "Total fees collected (in BNB)" # For creator/treasury addresses 112 | totalFeesCollectedInBNB: BigDecimal! 113 | 114 | "Transactions buy" 115 | buyTradeHistory: [Transaction!]! @derivedFrom(field: "buyer") 116 | 117 | "Transactions sold" 118 | sellTradeHistory: [Transaction!]! @derivedFrom(field: "seller") 119 | 120 | "Ask order history" 121 | askOrderHistory: [AskOrder!]! @derivedFrom(field: "seller") 122 | 123 | "Average price of tokens purchased (in BNB)" 124 | averageTokenPriceInBNBPurchased: BigDecimal! 125 | 126 | "Average price of tokens sold (in BNB)" 127 | averageTokenPriceInBNBSold: BigDecimal! 128 | } 129 | 130 | type AskOrder @entity { 131 | id: ID! 132 | 133 | "Block number" 134 | block: BigInt! 135 | 136 | "Timestamp" 137 | timestamp: BigInt! 138 | 139 | "Collection" 140 | collection: Collection! 141 | 142 | "NFT" 143 | nft: NFT! 144 | 145 | "Order type" 146 | orderType: OrderType! 147 | 148 | "Ask Price (in BNB)" 149 | askPrice: BigDecimal! 150 | 151 | "Seller" 152 | seller: User! 153 | } 154 | 155 | type Transaction @entity { 156 | id: ID! 157 | 158 | block: BigInt! 159 | 160 | "Timestamp" 161 | timestamp: BigInt! 162 | 163 | "Collection" 164 | collection: Collection! 165 | 166 | "NFT" 167 | nft: NFT! 168 | 169 | "Ask Price (in BNB)" 170 | askPrice: BigDecimal! 171 | 172 | "Net price to seller (in BNB)" 173 | netPrice: BigDecimal! 174 | 175 | "Buyer" 176 | buyer: User! 177 | 178 | "Seller" 179 | seller: User! 180 | 181 | "Whether the buyer used BNB" 182 | withBNB: Boolean! 183 | } 184 | 185 | type CollectionDayData @entity { 186 | id: ID! 187 | 188 | "Start date (timestamp)" 189 | date: Int! 190 | 191 | "Collection" 192 | collection: Collection! 193 | 194 | "Daily volume (in BNB)" 195 | dailyVolumeBNB: BigDecimal! 196 | 197 | "Daily unique trades" 198 | dailyTrades: BigInt! 199 | } 200 | 201 | type MarketPlaceDayData @entity { 202 | id: ID! 203 | 204 | "Start date (timestamp)" 205 | date: Int! 206 | 207 | "Daily volume (in BNB)" 208 | dailyVolumeBNB: BigDecimal! 209 | 210 | "Daily unique trades" 211 | dailyTrades: BigInt! 212 | } 213 | -------------------------------------------------------------------------------- /subgraphs/nft-market/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: NFT market for ERC721 tokens on Binance Smart Chain 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: ERC721NFTMarketV1 9 | network: bsc 10 | source: 11 | address: "0x17539cCa21C7933Df5c980172d22659B8C345C5A" 12 | abi: ERC721NFTMarketV1 13 | startBlock: 11352302 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/index.ts 19 | entities: 20 | - Collection 21 | - NFT 22 | - User 23 | - AskOrder 24 | - Transaction 25 | abis: 26 | - name: ERC721NFTMarketV1 27 | file: ./abis/ERC721NFTMarketV1.json 28 | - name: IERC721 29 | file: ./abis/IERC721.json 30 | - name: PancakeBunnies 31 | file: ./abis/PancakeBunnies.json 32 | eventHandlers: 33 | - event: AskCancel(indexed address,indexed address,indexed uint256) 34 | handler: handleAskCancel 35 | - event: AskNew(indexed address,indexed address,indexed uint256,uint256) 36 | handler: handleAskNew 37 | - event: AskUpdate(indexed address,indexed address,indexed uint256,uint256) 38 | handler: handleAskUpdate 39 | - event: CollectionClose(indexed address) 40 | handler: handleCollectionClose 41 | - event: CollectionNew(indexed address,indexed address,indexed address,uint256,uint256) 42 | handler: handleCollectionNew 43 | - event: CollectionUpdate(indexed address,indexed address,indexed address,uint256,uint256) 44 | handler: handleCollectionUpdate 45 | - event: RevenueClaim(indexed address,uint256) 46 | handler: handleRevenueClaim 47 | - event: Trade(indexed address,indexed uint256,indexed address,address,uint256,uint256,bool) 48 | handler: handleTrade 49 | -------------------------------------------------------------------------------- /subgraphs/pairs/abis/ERC20.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "name", 6 | "outputs": [ 7 | { 8 | "name": "", 9 | "type": "string" 10 | } 11 | ], 12 | "payable": false, 13 | "stateMutability": "view", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": true, 18 | "inputs": [], 19 | "name": "symbol", 20 | "outputs": [ 21 | { 22 | "name": "", 23 | "type": "string" 24 | } 25 | ], 26 | "payable": false, 27 | "stateMutability": "view", 28 | "type": "function" 29 | }, 30 | { 31 | "constant": true, 32 | "inputs": [], 33 | "name": "decimals", 34 | "outputs": [ 35 | { 36 | "name": "", 37 | "type": "uint8" 38 | } 39 | ], 40 | "payable": false, 41 | "stateMutability": "view", 42 | "type": "function" 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /subgraphs/pairs/abis/Factory.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "token0", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": true, 13 | "internalType": "address", 14 | "name": "token1", 15 | "type": "address" 16 | }, 17 | { 18 | "indexed": false, 19 | "internalType": "address", 20 | "name": "pair", 21 | "type": "address" 22 | }, 23 | { 24 | "indexed": false, 25 | "internalType": "uint256", 26 | "name": "", 27 | "type": "uint256" 28 | } 29 | ], 30 | "name": "PairCreated", 31 | "type": "event" 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /subgraphs/pairs/mappings/factory.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigInt } from "@graphprotocol/graph-ts"; 3 | import { Factory, Pair, Token } from "../generated/schema"; 4 | import { PairCreated } from "../generated/Factory/Factory"; 5 | import { fetchDecimals, fetchName, fetchSymbol } from "./utils/erc20"; 6 | 7 | // Constants 8 | let FACTORY_ADDRESS = "0xca143ce32fe78f1f7019d7d551a6402fc5350c73"; 9 | 10 | // BigNumber-like references 11 | let ZERO_BI = BigInt.fromI32(0); 12 | let ONE_BI = BigInt.fromI32(1); 13 | 14 | export function handlePairCreated(event: PairCreated): void { 15 | let factory = Factory.load(FACTORY_ADDRESS); 16 | if (factory === null) { 17 | // Factory 18 | factory = new Factory(FACTORY_ADDRESS); 19 | factory.totalPairs = ZERO_BI; 20 | factory.totalTokens = ZERO_BI; 21 | } 22 | 23 | let token0 = Token.load(event.params.token0.toHex()); 24 | if (token0 === null) { 25 | // Token0 26 | token0 = new Token(event.params.token0.toHex()); 27 | token0.name = fetchName(event.params.token0); 28 | token0.symbol = fetchSymbol(event.params.token0); 29 | token0.decimals = fetchDecimals(event.params.token0); 30 | 31 | // Factory 32 | factory.totalTokens = factory.totalTokens.plus(ONE_BI); 33 | } 34 | 35 | let token1 = Token.load(event.params.token1.toHex()); 36 | if (token1 === null) { 37 | // Token1 38 | token1 = new Token(event.params.token1.toHex()); 39 | token1.name = fetchName(event.params.token1); 40 | token1.symbol = fetchSymbol(event.params.token1); 41 | token1.decimals = fetchDecimals(event.params.token1); 42 | 43 | // Factory 44 | factory.totalTokens = factory.totalTokens.plus(ONE_BI); 45 | } 46 | 47 | // Pair 48 | let pair = new Pair(event.params.pair.toHex()); 49 | pair.token0 = token0.id; 50 | pair.token1 = token1.id; 51 | pair.name = token0.symbol.concat("-").concat(token1.symbol); 52 | pair.hash = event.transaction.hash; 53 | pair.block = event.block.number; 54 | pair.timestamp = event.block.timestamp; 55 | 56 | // Factory 57 | factory.totalPairs = factory.totalPairs.plus(ONE_BI); 58 | 59 | // Entities 60 | token0.save(); 61 | token1.save(); 62 | pair.save(); 63 | factory.save(); 64 | } 65 | -------------------------------------------------------------------------------- /subgraphs/pairs/mappings/utils/erc20.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigInt } from "@graphprotocol/graph-ts"; 3 | import { ERC20 } from "../../generated/Factory/ERC20"; 4 | 5 | export function fetchName(address: Address): string { 6 | let contract = ERC20.bind(address); 7 | 8 | let nameResult = contract.try_name(); 9 | if (!nameResult.reverted) { 10 | return nameResult.value; 11 | } 12 | 13 | return "unknown"; 14 | } 15 | 16 | export function fetchSymbol(address: Address): string { 17 | let contract = ERC20.bind(address); 18 | 19 | let symbolResult = contract.try_symbol(); 20 | if (!symbolResult.reverted) { 21 | return symbolResult.value; 22 | } 23 | 24 | return "unknown"; 25 | } 26 | 27 | export function fetchDecimals(address: Address): BigInt { 28 | let contract = ERC20.bind(address); 29 | 30 | let decimalResult = contract.try_decimals(); 31 | if (!decimalResult.reverted) { 32 | return BigInt.fromI32(decimalResult.value); 33 | } 34 | 35 | return null; 36 | } 37 | -------------------------------------------------------------------------------- /subgraphs/pairs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pairs", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/pairs subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/pairs/schema.graphql: -------------------------------------------------------------------------------- 1 | # Schema 2 | type _Schema_ 3 | # Token 4 | @fulltext( 5 | name: "tokenSearch", 6 | language: en 7 | algorithm: rank, 8 | include: [ 9 | { 10 | entity: "Token", 11 | fields: [ 12 | { name: "id" }, 13 | { name: "name" }, 14 | { name: "symbol" }, 15 | ] 16 | } 17 | ] 18 | ) 19 | # Pair 20 | @fulltext( 21 | name: "pairSearch", 22 | language: en 23 | algorithm: rank, 24 | include: [ 25 | { 26 | entity: "Pair", 27 | fields: [ 28 | { name: "id" }, 29 | { name: "name" }, 30 | ] 31 | } 32 | ] 33 | ) 34 | 35 | """ 36 | PancakeSwap Factory 37 | """ 38 | type Factory @entity { 39 | "ID (address)" 40 | id: ID! 41 | 42 | "Total of Pairs" 43 | totalPairs: BigInt! 44 | 45 | "Total of Tokens" 46 | totalTokens: BigInt! 47 | } 48 | 49 | """ 50 | PancakeSwap Tokens 51 | """ 52 | type Token @entity { 53 | "ID (address)" 54 | id: ID! 55 | 56 | "Name" 57 | name: String! 58 | "Symbol" 59 | symbol: String! 60 | "Decimals" 61 | decimals: BigInt 62 | } 63 | 64 | """ 65 | PancakeSwap Pairs (Cake-LP) 66 | """ 67 | type Pair @entity { 68 | "ID (address)" 69 | id: ID! 70 | 71 | "Token 0" 72 | token0: Token! 73 | "Token 1" 74 | token1: Token! 75 | 76 | "Token0 Symbol - Token1 Symbol" 77 | name: String! 78 | 79 | "Transaction Hash" 80 | hash: Bytes! 81 | "Block number" 82 | block: BigInt! 83 | "Block timestamp" 84 | timestamp: BigInt! 85 | } 86 | -------------------------------------------------------------------------------- /subgraphs/pairs/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Track Pairs and Tokens on PancakeSwap (v2) protocol 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: Factory 9 | network: bsc 10 | source: 11 | address: '0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73' 12 | abi: Factory 13 | startBlock: 6809737 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/factory.ts 19 | entities: 20 | - Factory 21 | - Token 22 | - Pair 23 | abis: 24 | - name: Factory 25 | file: ./abis/Factory.json 26 | - name: ERC20 27 | file: ./abis/ERC20.json 28 | eventHandlers: 29 | - event: PairCreated(indexed address,indexed address,address,uint256) 30 | handler: handlePairCreated 31 | -------------------------------------------------------------------------------- /subgraphs/pancake-squad/abis/ERC721.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [], 4 | "name": "name", 5 | "outputs": [ 6 | { 7 | "internalType": "string", 8 | "name": "", 9 | "type": "string" 10 | } 11 | ], 12 | "stateMutability": "view", 13 | "type": "function" 14 | }, 15 | { 16 | "inputs": [], 17 | "name": "symbol", 18 | "outputs": [ 19 | { 20 | "internalType": "string", 21 | "name": "", 22 | "type": "string" 23 | } 24 | ], 25 | "stateMutability": "view", 26 | "type": "function" 27 | }, 28 | { 29 | "inputs": [ 30 | { 31 | "internalType": "uint256", 32 | "name": "tokenId", 33 | "type": "uint256" 34 | } 35 | ], 36 | "name": "tokenURI", 37 | "outputs": [ 38 | { 39 | "internalType": "string", 40 | "name": "", 41 | "type": "string" 42 | } 43 | ], 44 | "stateMutability": "view", 45 | "type": "function" 46 | }, 47 | { 48 | "anonymous": false, 49 | "inputs": [ 50 | { 51 | "indexed": true, 52 | "internalType": "address", 53 | "name": "from", 54 | "type": "address" 55 | }, 56 | { 57 | "indexed": true, 58 | "internalType": "address", 59 | "name": "to", 60 | "type": "address" 61 | }, 62 | { 63 | "indexed": true, 64 | "internalType": "uint256", 65 | "name": "tokenId", 66 | "type": "uint256" 67 | } 68 | ], 69 | "name": "Transfer", 70 | "type": "event" 71 | } 72 | ] 73 | -------------------------------------------------------------------------------- /subgraphs/pancake-squad/mappings/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigInt } from "@graphprotocol/graph-ts"; 3 | import { Contract, Owner, Token, Transaction } from "../generated/schema"; 4 | import { Transfer } from "../generated/ERC721/ERC721"; 5 | import { toBigDecimal } from "./utils"; 6 | import { fetchName, fetchSymbol, fetchTokenUri } from "./utils/erc-721"; 7 | 8 | // Constants 9 | let CONTRACT_ADDRESS = "0x0a8901b0e25deb55a87524f0cc164e9644020eba"; 10 | let ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; 11 | 12 | // BigNumber-like references 13 | let ZERO_BI = BigInt.fromI32(0); 14 | let ONE_BI = BigInt.fromI32(1); 15 | 16 | export function handleTransfer(event: Transfer): void { 17 | let contract = Contract.load(CONTRACT_ADDRESS); 18 | if (contract === null) { 19 | // Contract 20 | contract = new Contract(CONTRACT_ADDRESS); 21 | contract.name = fetchName(); 22 | contract.symbol = fetchSymbol(); 23 | contract.totalTokens = ZERO_BI; 24 | contract.totalOwners = ZERO_BI; 25 | contract.totalTransactions = ZERO_BI; 26 | contract.save(); 27 | } 28 | contract.totalTransactions = contract.totalTransactions.plus(ONE_BI); 29 | contract.save(); 30 | 31 | let from = Owner.load(event.params.from.toHex()); 32 | if (from === null) { 33 | // Owner - as Sender 34 | from = new Owner(event.params.from.toHex()); 35 | from.totalTokens = ZERO_BI; 36 | from.totalTokensMinted = ZERO_BI; 37 | from.totalTransactions = ZERO_BI; 38 | from.block = event.block.number; 39 | from.createdAt = event.block.timestamp; 40 | from.updatedAt = event.block.timestamp; 41 | from.save(); 42 | 43 | // Contract 44 | contract.totalOwners = contract.totalOwners.plus(ONE_BI); 45 | contract.save(); 46 | } 47 | from.totalTokens = event.params.from.equals(Address.fromString(ZERO_ADDRESS)) 48 | ? from.totalTokens 49 | : from.totalTokens.minus(ONE_BI); 50 | from.totalTransactions = from.totalTransactions.plus(ONE_BI); 51 | from.updatedAt = event.block.timestamp; 52 | from.save(); 53 | 54 | let to = Owner.load(event.params.to.toHex()); 55 | if (to === null) { 56 | // Owner - as Receiver 57 | to = new Owner(event.params.to.toHex()); 58 | to.totalTokens = ZERO_BI; 59 | to.totalTokensMinted = ZERO_BI; 60 | to.totalTransactions = ZERO_BI; 61 | to.block = event.block.number; 62 | to.createdAt = event.block.timestamp; 63 | to.updatedAt = event.block.timestamp; 64 | to.save(); 65 | 66 | // Contract 67 | contract.totalOwners = contract.totalOwners.plus(ONE_BI); 68 | contract.save(); 69 | } 70 | to.totalTokens = to.totalTokens.plus(ONE_BI); 71 | to.totalTransactions = to.totalTransactions.plus(ONE_BI); 72 | to.updatedAt = event.block.timestamp; 73 | to.save(); 74 | 75 | let token = Token.load(event.params.tokenId.toString()); 76 | if (token === null) { 77 | // Token 78 | token = new Token(event.params.tokenId.toString()); 79 | token.minter = to.id; 80 | token.owner = to.id; 81 | token.burned = false; 82 | token.uri = fetchTokenUri(event.params.tokenId); 83 | token.totalTransactions = ZERO_BI; 84 | token.block = event.block.number; 85 | token.createdAt = event.block.timestamp; 86 | token.updatedAt = event.block.timestamp; 87 | token.save(); 88 | 89 | // Owner - as Receiver 90 | to.totalTokensMinted = to.totalTokensMinted.plus(ONE_BI); 91 | to.save(); 92 | 93 | // Contract 94 | contract.totalTokens = contract.totalTokens.plus(ONE_BI); 95 | contract.save(); 96 | } 97 | token.owner = to.id; 98 | token.burned = event.params.to.equals(Address.fromString(ZERO_ADDRESS)); 99 | token.totalTransactions = token.totalTransactions.plus(ONE_BI); 100 | token.updatedAt = event.block.timestamp; 101 | token.save(); 102 | 103 | // Transaction 104 | let transaction = new Transaction(event.transaction.hash.toHex()); 105 | transaction.hash = event.transaction.hash; 106 | transaction.from = from.id; 107 | transaction.to = to.id; 108 | transaction.token = token.id; 109 | transaction.gasUsed = event.transaction.gasUsed; 110 | transaction.gasPrice = toBigDecimal(event.transaction.gasPrice, 9); 111 | transaction.block = event.block.number; 112 | transaction.timestamp = event.block.timestamp; 113 | transaction.save(); 114 | } 115 | -------------------------------------------------------------------------------- /subgraphs/pancake-squad/mappings/utils/erc-721.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigInt, dataSource } from "@graphprotocol/graph-ts"; 3 | import { ERC721 } from "../../generated/ERC721/ERC721"; 4 | 5 | export function fetchName(): string { 6 | let contract = ERC721.bind(dataSource.address()); 7 | 8 | let nameResult = contract.try_name(); 9 | if (!nameResult.reverted) { 10 | return nameResult.value; 11 | } 12 | 13 | return "unknown"; 14 | } 15 | 16 | export function fetchSymbol(): string { 17 | let contract = ERC721.bind(dataSource.address()); 18 | 19 | let symbolResult = contract.try_symbol(); 20 | if (!symbolResult.reverted) { 21 | return symbolResult.value; 22 | } 23 | 24 | return "unknown"; 25 | } 26 | 27 | export function fetchTokenUri(tokenID: BigInt): string | null { 28 | let contract = ERC721.bind(dataSource.address()); 29 | 30 | let uriResult = contract.try_tokenURI(tokenID); 31 | if (!uriResult.reverted) { 32 | return uriResult.value; 33 | } 34 | 35 | return null; 36 | } 37 | -------------------------------------------------------------------------------- /subgraphs/pancake-squad/mappings/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigDecimal, BigInt } from "@graphprotocol/graph-ts"; 3 | 4 | export function toBigDecimal(quantity: BigInt, decimals: i32 = 18): BigDecimal { 5 | return quantity.divDecimal( 6 | BigInt.fromI32(10) 7 | .pow(decimals as u8) 8 | .toBigDecimal() 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /subgraphs/pancake-squad/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pancake-squad", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "MIT", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/pancake-squad subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/pancake-squad/schema.graphql: -------------------------------------------------------------------------------- 1 | # Schema 2 | type _Schema_ 3 | # Token 4 | @fulltext( 5 | name: "tokenSearch" 6 | language: en 7 | algorithm: rank 8 | include: [{ entity: "Token", fields: [{ name: "id" }] }] 9 | ) 10 | # Owner 11 | @fulltext( 12 | name: "ownerSearch" 13 | language: en 14 | algorithm: rank 15 | include: [{ entity: "Owner", fields: [{ name: "id" }] }] 16 | ) 17 | 18 | """ 19 | Pancake Squad (contract) 20 | """ 21 | type Contract @entity { 22 | "ID (address)" 23 | id: ID! 24 | 25 | "Name" 26 | name: String! 27 | 28 | "Symbol" 29 | symbol: String! 30 | 31 | "Total of Tokens" 32 | totalTokens: BigInt! 33 | 34 | "Total of Owners" 35 | totalOwners: BigInt! 36 | 37 | "Total of Transactions" 38 | totalTransactions: BigInt! 39 | } 40 | 41 | """ 42 | Owners 43 | """ 44 | type Owner @entity { 45 | "ID" 46 | id: ID! 47 | 48 | "List of Tokens" 49 | tokens: [Token!]! @derivedFrom(field: "owner") 50 | "Total of Tokens" 51 | totalTokens: BigInt! 52 | "Total of Tokens Minted" 53 | totalTokensMinted: BigInt! 54 | 55 | "List of Transactions (as Sender)" 56 | fromTransactions: [Transaction!]! @derivedFrom(field: "from") 57 | "List of Transactions (as Receiver)" 58 | toTransactions: [Transaction!]! @derivedFrom(field: "to") 59 | "Total of Transactions" 60 | totalTransactions: BigInt! 61 | 62 | "Block number" 63 | block: BigInt! 64 | "Created At" 65 | createdAt: BigInt! 66 | "Updated At" 67 | updatedAt: BigInt! 68 | } 69 | 70 | """ 71 | Tokens 72 | """ 73 | type Token @entity { 74 | "ID" 75 | id: ID! 76 | 77 | "Minter" 78 | minter: Owner! 79 | 80 | "Owner" 81 | owner: Owner! 82 | 83 | "Burned" 84 | burned: Boolean! 85 | 86 | "URI" 87 | uri: String 88 | 89 | "List of Transactions" 90 | transactions: [Transaction!]! @derivedFrom(field: "token") 91 | "Total of Transactions" 92 | totalTransactions: BigInt! 93 | 94 | "Block number" 95 | block: BigInt! 96 | "Created At" 97 | createdAt: BigInt! 98 | "Updated At" 99 | updatedAt: BigInt! 100 | } 101 | 102 | """ 103 | Transactions 104 | """ 105 | type Transaction @entity { 106 | "ID (hash)" 107 | id: ID! 108 | 109 | "Hash" 110 | hash: Bytes! 111 | 112 | "Sender" 113 | from: Owner! 114 | "Receiver" 115 | to: Owner! 116 | 117 | "Token" 118 | token: Token! 119 | 120 | "Gas Used" 121 | gasUsed: BigInt! 122 | "Gas Price (in wei)" 123 | gasPrice: BigDecimal! 124 | 125 | "Block number" 126 | block: BigInt! 127 | "Block timestamp" 128 | timestamp: BigInt! 129 | } 130 | -------------------------------------------------------------------------------- /subgraphs/pancake-squad/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Pancake Squad NFT Collection 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: ERC721 9 | network: bsc 10 | source: 11 | address: '0x0a8901b0E25DEb55A87524f0cC164E9644020EBA' 12 | abi: ERC721 13 | startBlock: 11553810 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/index.ts 19 | entities: 20 | - Contract 21 | - Owner 22 | - Token 23 | - Transaction 24 | abis: 25 | - name: ERC721 26 | file: ./abis/ERC721.json 27 | eventHandlers: 28 | - event: Transfer(indexed address,indexed address,indexed uint256) 29 | handler: handleTransfer 30 | -------------------------------------------------------------------------------- /subgraphs/prediction/v1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prediction-v1", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/prediction subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/prediction/v1/schema.graphql: -------------------------------------------------------------------------------- 1 | enum Position { 2 | Bull 3 | Bear 4 | House 5 | } 6 | 7 | type Market @entity { 8 | id: ID! 9 | 10 | epoch: Round 11 | paused: Boolean! 12 | 13 | totalUsers: BigInt! 14 | totalBets: BigInt! 15 | totalBetsBull: BigInt! 16 | totalBetsBear: BigInt! 17 | totalBNB: BigDecimal! 18 | totalBNBBull: BigDecimal! 19 | totalBNBBear: BigDecimal! 20 | totalBNBTreasury: BigDecimal! 21 | 22 | rewardRate: BigInt! 23 | treasuryRate: BigInt! 24 | } 25 | 26 | type Round @entity { 27 | id: ID! 28 | 29 | epoch: BigInt! 30 | position: Position 31 | failed: Boolean 32 | 33 | previous: Round 34 | 35 | # Start 36 | startAt: BigInt! 37 | startBlock: BigInt! 38 | startHash: Bytes! 39 | 40 | # Lock 41 | lockAt: BigInt 42 | lockBlock: BigInt 43 | lockHash: Bytes 44 | lockPrice: BigDecimal 45 | 46 | # End 47 | endAt: BigInt 48 | endBlock: BigInt 49 | endHash: Bytes 50 | closePrice: BigDecimal # endPrice 51 | 52 | # Bets 53 | totalBets: BigInt! 54 | totalAmount: BigDecimal! 55 | totalAmountTreasury: BigDecimal 56 | bullBets: BigInt! 57 | bullAmount: BigDecimal! 58 | bearBets: BigInt! 59 | bearAmount: BigDecimal! 60 | bets: [Bet!]! @derivedFrom(field: "round") 61 | } 62 | 63 | type User @entity { 64 | id: ID! 65 | 66 | # Address 67 | address: Bytes! 68 | 69 | createdAt: BigInt! 70 | updatedAt: BigInt! 71 | 72 | # Block 73 | block: BigInt! 74 | 75 | # Bets 76 | totalBets: BigInt! 77 | totalBNB: BigDecimal! 78 | bets: [Bet!]! @derivedFrom(field: "user") 79 | } 80 | 81 | type Bet @entity { 82 | id: ID! 83 | 84 | # epoch 85 | round: Round! 86 | 87 | user: User! 88 | hash: Bytes! 89 | 90 | amount: BigDecimal! 91 | position: Position! 92 | claimed: Boolean! 93 | claimedAmount: BigDecimal 94 | claimedHash: Bytes 95 | 96 | createdAt: BigInt! 97 | updatedAt: BigInt! 98 | 99 | # Block 100 | block: BigInt! 101 | } 102 | -------------------------------------------------------------------------------- /subgraphs/prediction/v1/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Pancake Prediction 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: Prediction 9 | network: bsc 10 | source: 11 | address: '0x516ffd7D1e0Ca40b1879935B2De87cb20Fc1124b' 12 | abi: Prediction 13 | startBlock: 6950840 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/index.ts 19 | entities: 20 | - Market 21 | - Round 22 | - User 23 | - Bet 24 | abis: 25 | - name: Prediction 26 | file: ./abis/Prediction.json 27 | eventHandlers: 28 | - event: StartRound(indexed uint256,uint256) 29 | handler: handleStartRound 30 | - event: LockRound(indexed uint256,uint256,int256) 31 | handler: handleLockRound 32 | - event: EndRound(indexed uint256,uint256,int256) 33 | handler: handleEndRound 34 | - event: BetBull(indexed address,indexed uint256,uint256) 35 | handler: handleBetBull 36 | - event: BetBear(indexed address,indexed uint256,uint256) 37 | handler: handleBetBear 38 | - event: Claim(indexed address,indexed uint256,uint256) 39 | handler: handleClaim 40 | - event: Pause(uint256) 41 | handler: handlePause 42 | - event: Unpause(uint256) 43 | handler: handleUnpause 44 | - event: RatesUpdated(indexed uint256,uint256,uint256) 45 | handler: handleRatesUpdated 46 | - event: RewardsCalculated(indexed uint256,uint256,uint256,uint256) 47 | handler: handleRewardsCalculated 48 | -------------------------------------------------------------------------------- /subgraphs/prediction/v2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prediction-v2", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/prediction-v2 subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/prediction/v2/schema.graphql: -------------------------------------------------------------------------------- 1 | enum Position { 2 | Bull 3 | Bear 4 | House 5 | } 6 | 7 | type Market @entity { 8 | id: ID! 9 | 10 | epoch: Round 11 | paused: Boolean! 12 | 13 | # Users 14 | totalUsers: BigInt! 15 | 16 | # Bets 17 | totalBets: BigInt! 18 | totalBetsBull: BigInt! 19 | totalBetsBear: BigInt! 20 | totalBNB: BigDecimal! 21 | totalBNBBull: BigDecimal! 22 | totalBNBBear: BigDecimal! 23 | totalBNBTreasury: BigDecimal! 24 | 25 | # Statistics 26 | totalBetsClaimed: BigInt! 27 | totalBNBClaimed: BigDecimal! 28 | winRate: BigDecimal! 29 | averageBNB: BigDecimal! 30 | netBNB: BigDecimal! 31 | } 32 | 33 | type Round @entity { 34 | id: ID! 35 | 36 | epoch: BigInt! 37 | position: Position 38 | failed: Boolean 39 | 40 | previous: Round 41 | 42 | # Start 43 | startAt: BigInt! 44 | startBlock: BigInt! 45 | startHash: Bytes! 46 | 47 | # Lock 48 | lockAt: BigInt 49 | lockBlock: BigInt 50 | lockHash: Bytes 51 | lockPrice: BigDecimal 52 | lockRoundId: BigInt 53 | 54 | # End 55 | closeAt: BigInt 56 | closeBlock: BigInt 57 | closeHash: Bytes 58 | closePrice: BigDecimal 59 | closeRoundId: BigInt 60 | 61 | # Bets 62 | totalBets: BigInt! 63 | totalAmount: BigDecimal! 64 | bullBets: BigInt! 65 | bullAmount: BigDecimal! 66 | bearBets: BigInt! 67 | bearAmount: BigDecimal! 68 | bets: [Bet!]! @derivedFrom(field: "round") 69 | } 70 | 71 | type User @entity { 72 | id: ID! 73 | 74 | createdAt: BigInt! 75 | updatedAt: BigInt! 76 | 77 | block: BigInt! 78 | 79 | # Bets 80 | totalBets: BigInt! 81 | totalBetsBull: BigInt! 82 | totalBetsBear: BigInt! 83 | totalBNB: BigDecimal! 84 | totalBNBBull: BigDecimal! 85 | totalBNBBear: BigDecimal! 86 | bets: [Bet!]! @derivedFrom(field: "user") 87 | 88 | # Statistics 89 | totalBetsClaimed: BigInt! 90 | totalBNBClaimed: BigDecimal! 91 | winRate: BigDecimal! 92 | averageBNB: BigDecimal! 93 | netBNB: BigDecimal! 94 | } 95 | 96 | type Bet @entity { 97 | id: ID! 98 | 99 | # epoch 100 | round: Round! 101 | 102 | user: User! 103 | hash: Bytes! 104 | 105 | amount: BigDecimal! 106 | position: Position! 107 | 108 | claimed: Boolean! 109 | claimedAt: BigInt 110 | claimedBlock: BigInt 111 | claimedHash: Bytes 112 | claimedBNB: BigDecimal 113 | claimedNetBNB: BigDecimal 114 | 115 | createdAt: BigInt! 116 | updatedAt: BigInt! 117 | 118 | block: BigInt! 119 | } 120 | -------------------------------------------------------------------------------- /subgraphs/prediction/v2/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Pancake Prediction V2 3 | features: 4 | - grafting 5 | graft: 6 | base: QmaHRgUYDNKEXueDTA1Ntnv4rTWsignS9LojZFwyBr2mVm 7 | block: 17140600 8 | repository: https://github.com/pancakeswap 9 | schema: 10 | file: ./schema.graphql 11 | dataSources: 12 | - kind: ethereum/contract 13 | name: PredictionV2 14 | network: bsc 15 | source: 16 | address: '0x18B2A687610328590Bc8F2e5fEdDe3b582A49cdA' 17 | abi: PredictionV2 18 | startBlock: 10333825 19 | mapping: 20 | kind: ethereum/events 21 | apiVersion: 0.0.4 22 | language: wasm/assemblyscript 23 | file: ./mappings/index.ts 24 | entities: 25 | - Market 26 | - Round 27 | - User 28 | - Bet 29 | abis: 30 | - name: PredictionV2 31 | file: ./abis/PredictionV2.json 32 | eventHandlers: 33 | - event: StartRound(indexed uint256) 34 | handler: handleStartRound 35 | - event: LockRound(indexed uint256,indexed uint256,int256) 36 | handler: handleLockRound 37 | - event: EndRound(indexed uint256,indexed uint256,int256) 38 | handler: handleEndRound 39 | - event: BetBull(indexed address,indexed uint256,uint256) 40 | handler: handleBetBull 41 | - event: BetBear(indexed address,indexed uint256,uint256) 42 | handler: handleBetBear 43 | - event: Claim(indexed address,indexed uint256,uint256) 44 | handler: handleClaim 45 | - event: Pause(indexed uint256) 46 | handler: handlePause 47 | - event: Unpause(indexed uint256) 48 | handler: handleUnpause 49 | - event: RewardsCalculated(indexed uint256,uint256,uint256,uint256) 50 | handler: handleRewardsCalculated 51 | -------------------------------------------------------------------------------- /subgraphs/profile/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "profile", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/profile subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/profile/schema.graphql: -------------------------------------------------------------------------------- 1 | type Team @entity { 2 | id: ID! 3 | 4 | name: String! 5 | isJoinable: Boolean! 6 | 7 | # Block number when the team was created. 8 | block: BigInt! 9 | timestamp: BigInt! 10 | 11 | # Users 12 | totalUsers: BigInt! 13 | users: [User!]! @derivedFrom(field: "team") 14 | 15 | # Points with campaignId 16 | totalPoints: BigInt! 17 | points: [Point!]! @derivedFrom(field: "team") 18 | } 19 | 20 | type User @entity { 21 | id: ID! # address 22 | 23 | internalId: BigInt! # auto increment 24 | 25 | isActive: Boolean! 26 | 27 | createdAt: BigInt! 28 | updatedAt: BigInt! 29 | 30 | # Block number when the user was created. 31 | block: BigInt! 32 | 33 | # Team 34 | team: Team! 35 | 36 | # Points with campaignId 37 | totalPoints: BigInt! 38 | points: [Point!]! @derivedFrom(field: "user") 39 | 40 | nftAddress: Bytes 41 | tokenId: BigInt 42 | } 43 | 44 | type Point @entity { 45 | id: ID! # address/teamId + campaignId 46 | 47 | # Use optionnal dependecy to avoid having to `.concat` each point(s). 48 | team: Team 49 | user: User 50 | 51 | points: BigInt! 52 | campaignId: BigInt! 53 | 54 | # Transaction 55 | hash: Bytes! 56 | 57 | # Block number when the point was triggered. 58 | block: BigInt! 59 | timestamp: BigInt! 60 | } 61 | 62 | type IdIncrement @entity { 63 | id: ID! # address 64 | 65 | autoIncrement: BigInt! # auto increment 66 | } -------------------------------------------------------------------------------- /subgraphs/profile/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Pancake Profile 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: Profile 9 | network: bsc 10 | source: 11 | address: '0xDf4dBf6536201370F95e06A0F8a7a70fE40E388a' 12 | abi: Profile 13 | startBlock: 4570433 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/index.ts 19 | entities: 20 | - Team 21 | - User 22 | - Points 23 | abis: 24 | - name: Profile 25 | file: ./abis/Profile.json 26 | eventHandlers: 27 | - event: TeamAdd(uint256,string) 28 | handler: handleTeamAdd 29 | - event: TeamPointIncrease(indexed uint256,uint256,indexed uint256) 30 | handler: handleTeamPointIncrease 31 | - event: UserNew(indexed address,uint256,address,uint256) 32 | handler: handleUserNew 33 | - event: UserUpdate(indexed address,address,uint256) 34 | handler: handleUserUpdate 35 | - event: UserPause(indexed address,uint256) 36 | handler: handleUserPause 37 | - event: UserReactivate(indexed address,uint256,address,uint256) 38 | handler: handleUserReactivate 39 | - event: UserChangeTeam(indexed address,uint256,uint256) 40 | handler: handleUserChangeTeam 41 | - event: UserPointIncrease(indexed address,uint256,indexed uint256) 42 | handler: handleUserPointIncrease 43 | - event: UserPointIncreaseMultiple(address[],uint256,indexed uint256) 44 | handler: handleUserPointIncreaseMultiple 45 | -------------------------------------------------------------------------------- /subgraphs/smartchef/abis/ERC20.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "name", 6 | "outputs": [ 7 | { 8 | "name": "", 9 | "type": "string" 10 | } 11 | ], 12 | "payable": false, 13 | "stateMutability": "view", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": false, 18 | "inputs": [ 19 | { 20 | "name": "_spender", 21 | "type": "address" 22 | }, 23 | { 24 | "name": "_value", 25 | "type": "uint256" 26 | } 27 | ], 28 | "name": "approve", 29 | "outputs": [ 30 | { 31 | "name": "", 32 | "type": "bool" 33 | } 34 | ], 35 | "payable": false, 36 | "stateMutability": "nonpayable", 37 | "type": "function" 38 | }, 39 | { 40 | "constant": true, 41 | "inputs": [], 42 | "name": "totalSupply", 43 | "outputs": [ 44 | { 45 | "name": "", 46 | "type": "uint256" 47 | } 48 | ], 49 | "payable": false, 50 | "stateMutability": "view", 51 | "type": "function" 52 | }, 53 | { 54 | "constant": false, 55 | "inputs": [ 56 | { 57 | "name": "_from", 58 | "type": "address" 59 | }, 60 | { 61 | "name": "_to", 62 | "type": "address" 63 | }, 64 | { 65 | "name": "_value", 66 | "type": "uint256" 67 | } 68 | ], 69 | "name": "transferFrom", 70 | "outputs": [ 71 | { 72 | "name": "", 73 | "type": "bool" 74 | } 75 | ], 76 | "payable": false, 77 | "stateMutability": "nonpayable", 78 | "type": "function" 79 | }, 80 | { 81 | "constant": true, 82 | "inputs": [], 83 | "name": "decimals", 84 | "outputs": [ 85 | { 86 | "name": "", 87 | "type": "uint8" 88 | } 89 | ], 90 | "payable": false, 91 | "stateMutability": "view", 92 | "type": "function" 93 | }, 94 | { 95 | "constant": true, 96 | "inputs": [ 97 | { 98 | "name": "_owner", 99 | "type": "address" 100 | } 101 | ], 102 | "name": "balanceOf", 103 | "outputs": [ 104 | { 105 | "name": "balance", 106 | "type": "uint256" 107 | } 108 | ], 109 | "payable": false, 110 | "stateMutability": "view", 111 | "type": "function" 112 | }, 113 | { 114 | "constant": true, 115 | "inputs": [], 116 | "name": "symbol", 117 | "outputs": [ 118 | { 119 | "name": "", 120 | "type": "string" 121 | } 122 | ], 123 | "payable": false, 124 | "stateMutability": "view", 125 | "type": "function" 126 | }, 127 | { 128 | "constant": false, 129 | "inputs": [ 130 | { 131 | "name": "_to", 132 | "type": "address" 133 | }, 134 | { 135 | "name": "_value", 136 | "type": "uint256" 137 | } 138 | ], 139 | "name": "transfer", 140 | "outputs": [ 141 | { 142 | "name": "", 143 | "type": "bool" 144 | } 145 | ], 146 | "payable": false, 147 | "stateMutability": "nonpayable", 148 | "type": "function" 149 | }, 150 | { 151 | "constant": true, 152 | "inputs": [ 153 | { 154 | "name": "_owner", 155 | "type": "address" 156 | }, 157 | { 158 | "name": "_spender", 159 | "type": "address" 160 | } 161 | ], 162 | "name": "allowance", 163 | "outputs": [ 164 | { 165 | "name": "", 166 | "type": "uint256" 167 | } 168 | ], 169 | "payable": false, 170 | "stateMutability": "view", 171 | "type": "function" 172 | }, 173 | { 174 | "payable": true, 175 | "stateMutability": "payable", 176 | "type": "fallback" 177 | }, 178 | { 179 | "anonymous": false, 180 | "inputs": [ 181 | { 182 | "indexed": true, 183 | "name": "owner", 184 | "type": "address" 185 | }, 186 | { 187 | "indexed": true, 188 | "name": "spender", 189 | "type": "address" 190 | }, 191 | { 192 | "indexed": false, 193 | "name": "value", 194 | "type": "uint256" 195 | } 196 | ], 197 | "name": "Approval", 198 | "type": "event" 199 | }, 200 | { 201 | "anonymous": false, 202 | "inputs": [ 203 | { 204 | "indexed": true, 205 | "name": "from", 206 | "type": "address" 207 | }, 208 | { 209 | "indexed": true, 210 | "name": "to", 211 | "type": "address" 212 | }, 213 | { 214 | "indexed": false, 215 | "name": "value", 216 | "type": "uint256" 217 | } 218 | ], 219 | "name": "Transfer", 220 | "type": "event" 221 | } 222 | ] 223 | -------------------------------------------------------------------------------- /subgraphs/smartchef/abis/ERC20NameBytes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "name", 6 | "outputs": [ 7 | { 8 | "internalType": "bytes32", 9 | "name": "", 10 | "type": "bytes32" 11 | } 12 | ], 13 | "payable": false, 14 | "stateMutability": "view", 15 | "type": "function" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /subgraphs/smartchef/abis/ERC20SymbolBytes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "symbol", 6 | "outputs": [ 7 | { 8 | "internalType": "bytes32", 9 | "name": "", 10 | "type": "bytes32" 11 | } 12 | ], 13 | "payable": false, 14 | "stateMutability": "view", 15 | "type": "function" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /subgraphs/smartchef/abis/SmartChefFactory.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [], 4 | "stateMutability": "nonpayable", 5 | "type": "constructor" 6 | }, 7 | { 8 | "anonymous": false, 9 | "inputs": [ 10 | { 11 | "indexed": true, 12 | "internalType": "address", 13 | "name": "smartChef", 14 | "type": "address" 15 | } 16 | ], 17 | "name": "NewSmartChefContract", 18 | "type": "event" 19 | }, 20 | { 21 | "anonymous": false, 22 | "inputs": [ 23 | { 24 | "indexed": true, 25 | "internalType": "address", 26 | "name": "previousOwner", 27 | "type": "address" 28 | }, 29 | { 30 | "indexed": true, 31 | "internalType": "address", 32 | "name": "newOwner", 33 | "type": "address" 34 | } 35 | ], 36 | "name": "OwnershipTransferred", 37 | "type": "event" 38 | }, 39 | { 40 | "inputs": [ 41 | { 42 | "internalType": "contract IBEP20", 43 | "name": "_stakedToken", 44 | "type": "address" 45 | }, 46 | { 47 | "internalType": "contract IBEP20", 48 | "name": "_rewardToken", 49 | "type": "address" 50 | }, 51 | { 52 | "internalType": "uint256", 53 | "name": "_rewardPerBlock", 54 | "type": "uint256" 55 | }, 56 | { 57 | "internalType": "uint256", 58 | "name": "_startBlock", 59 | "type": "uint256" 60 | }, 61 | { 62 | "internalType": "uint256", 63 | "name": "_bonusEndBlock", 64 | "type": "uint256" 65 | }, 66 | { 67 | "internalType": "uint256", 68 | "name": "_poolLimitPerUser", 69 | "type": "uint256" 70 | }, 71 | { 72 | "internalType": "address", 73 | "name": "_admin", 74 | "type": "address" 75 | } 76 | ], 77 | "name": "deployPool", 78 | "outputs": [], 79 | "stateMutability": "nonpayable", 80 | "type": "function" 81 | }, 82 | { 83 | "inputs": [], 84 | "name": "owner", 85 | "outputs": [ 86 | { 87 | "internalType": "address", 88 | "name": "", 89 | "type": "address" 90 | } 91 | ], 92 | "stateMutability": "view", 93 | "type": "function" 94 | }, 95 | { 96 | "inputs": [], 97 | "name": "renounceOwnership", 98 | "outputs": [], 99 | "stateMutability": "nonpayable", 100 | "type": "function" 101 | }, 102 | { 103 | "inputs": [ 104 | { 105 | "internalType": "address", 106 | "name": "newOwner", 107 | "type": "address" 108 | } 109 | ], 110 | "name": "transferOwnership", 111 | "outputs": [], 112 | "stateMutability": "nonpayable", 113 | "type": "function" 114 | } 115 | ] 116 | -------------------------------------------------------------------------------- /subgraphs/smartchef/mappings/factory.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigInt, log } from "@graphprotocol/graph-ts"; 3 | import { Factory } from "../generated/schema"; 4 | import { NewSmartChefContract } from "../generated/SmartChefFactory/SmartChefFactory"; 5 | import { BLACKLISTED_ADDRESSES, convertTokenToDecimal } from "./utils"; 6 | import { SmartChefInitializable } from "../generated/templates"; 7 | import { getOrCreateToken } from "./utils/erc20"; 8 | import { 9 | fetchEndBlock, 10 | fetchRewardPerBlock, 11 | fetchRewardToken, 12 | fetchStakeToken, 13 | fetchStartBlock, 14 | fetchUserLimit, 15 | getOrCreateSmartChef, 16 | } from "./utils/smartchef"; 17 | 18 | let ZERO_BI = BigInt.fromI32(0); 19 | let ONE_BI = BigInt.fromI32(1); 20 | let FACTORY_ADDRESS = "0x927158be21fe3d4da7e96931bb27fd5059a8cbc2"; 21 | let FACTORY_V2_ADDRESS = "0xFfF5812C35eC100dF51D5C9842e8cC3fe60f9ad7"; 22 | 23 | export function handleNewSmartChefContract(event: NewSmartChefContract): void { 24 | // Do not process some SmartChef smart contract, hiccup. 25 | if (BLACKLISTED_ADDRESSES.includes(event.params.smartChef.toHex())) { 26 | return; 27 | } 28 | 29 | let factory = Factory.load(FACTORY_ADDRESS); 30 | if (factory === null) { 31 | factory = new Factory(FACTORY_ADDRESS); 32 | factory.totalSmartChef = ZERO_BI; 33 | factory.save(); 34 | } 35 | factory.totalSmartChef = factory.totalSmartChef.plus(ONE_BI); 36 | factory.save(); 37 | 38 | process(event); 39 | } 40 | 41 | export function handleNewSmartChefContractV2(event: NewSmartChefContract): void { 42 | let factory = Factory.load(FACTORY_V2_ADDRESS); 43 | if (factory === null) { 44 | factory = new Factory(FACTORY_V2_ADDRESS); 45 | factory.totalSmartChef = ZERO_BI; 46 | factory.save(); 47 | } 48 | factory.totalSmartChef = factory.totalSmartChef.plus(ONE_BI); 49 | factory.save(); 50 | 51 | process(event); 52 | } 53 | 54 | function process(event: NewSmartChefContract): void { 55 | let stakeTokenAddress = fetchStakeToken(event.params.smartChef); 56 | let stakeToken = getOrCreateToken(stakeTokenAddress); 57 | 58 | let earnTokenAddress = fetchRewardToken(event.params.smartChef); 59 | let earnToken = getOrCreateToken(earnTokenAddress); 60 | 61 | let smartChef = getOrCreateSmartChef(event.params.smartChef); 62 | smartChef.stakeToken = stakeToken.id; 63 | smartChef.earnToken = earnToken.id; 64 | smartChef.startBlock = fetchStartBlock(event.params.smartChef); 65 | smartChef.endBlock = fetchEndBlock(event.params.smartChef); 66 | smartChef.reward = convertTokenToDecimal(fetchRewardPerBlock(event.params.smartChef), earnToken.decimals); 67 | 68 | let userLimit = fetchUserLimit(event.params.smartChef); 69 | if (userLimit.gt(ZERO_BI)) { 70 | smartChef.limit = convertTokenToDecimal(userLimit, stakeToken.decimals); 71 | } 72 | 73 | smartChef.block = event.block.number; 74 | smartChef.timestamp = event.block.timestamp; 75 | smartChef.save(); 76 | SmartChefInitializable.create(event.params.smartChef); 77 | log.info("SmartChef initialized: {}", [smartChef.id]); 78 | } 79 | -------------------------------------------------------------------------------- /subgraphs/smartchef/mappings/index.ts: -------------------------------------------------------------------------------- 1 | import { Address, BigInt, dataSource } from "@graphprotocol/graph-ts"; 2 | import { 3 | Deposit, 4 | EmergencyWithdraw, 5 | NewRewardPerBlock, 6 | NewStartAndEndBlocks, 7 | Withdraw, 8 | } from "../generated/templates/SmartChefInitializable/SmartChef"; 9 | import { convertTokenToDecimal } from "./utils"; 10 | import { getOrCreateToken } from "./utils/erc20"; 11 | import { getOrCreateSmartChef } from "./utils/smartchef"; 12 | import { getOrCreateUser } from "./utils/user"; 13 | 14 | export function handleDeposit(event: Deposit): void { 15 | const user = getOrCreateUser(dataSource.address(), event.params.user); 16 | const pool = getOrCreateSmartChef(dataSource.address()); 17 | user.stakeToken = pool.stakeToken; 18 | user.stakeAmount = user.stakeAmount.plus(event.params.amount); 19 | user.save(); 20 | } 21 | 22 | export function handleWithdraw(event: Withdraw): void { 23 | const user = getOrCreateUser(dataSource.address(), event.params.user); 24 | user.stakeAmount = user.stakeAmount.minus(event.params.amount); 25 | user.save(); 26 | } 27 | 28 | export function handleEmergencyWithdraw(event: EmergencyWithdraw): void { 29 | const user = getOrCreateUser(dataSource.address(), event.params.user); 30 | user.stakeAmount = BigInt.fromI32(0); 31 | user.save(); 32 | } 33 | 34 | export function handleNewStartAndEndBlocks(event: NewStartAndEndBlocks): void { 35 | const pool = getOrCreateSmartChef(dataSource.address()); 36 | pool.startBlock = event.params.startBlock; 37 | pool.endBlock = event.params.endBlock; 38 | pool.save(); 39 | } 40 | 41 | export function handleNewRewardPerBlock(event: NewRewardPerBlock): void { 42 | const pool = getOrCreateSmartChef(dataSource.address()); 43 | const earnToken = getOrCreateToken(Address.fromString(pool.earnToken)); 44 | pool.reward = convertTokenToDecimal(event.params.rewardPerBlock, earnToken.decimals); 45 | pool.save(); 46 | } 47 | -------------------------------------------------------------------------------- /subgraphs/smartchef/mappings/utils/erc20.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigInt } from "@graphprotocol/graph-ts"; 3 | import { Token } from "../../generated/schema"; 4 | import { ERC20 } from "../../generated/SmartChefFactory/ERC20"; 5 | import { ERC20NameBytes } from "../../generated/SmartChefFactory/ERC20NameBytes"; 6 | import { ERC20SymbolBytes } from "../../generated/SmartChefFactory/ERC20SymbolBytes"; 7 | 8 | export function isNullBnbValue(value: string): boolean { 9 | return value == "0x0000000000000000000000000000000000000000000000000000000000000001"; 10 | } 11 | 12 | export function fetchTokenName(tokenAddress: Address): string { 13 | let contract = ERC20.bind(tokenAddress); 14 | let contractNameBytes = ERC20NameBytes.bind(tokenAddress); 15 | 16 | let nameValue = "unknown"; 17 | let nameResult = contract.try_name(); 18 | if (nameResult.reverted) { 19 | let nameResultBytes = contractNameBytes.try_name(); 20 | if (!nameResultBytes.reverted) { 21 | if (!isNullBnbValue(nameResultBytes.value.toHex())) { 22 | nameValue = nameResultBytes.value.toString(); 23 | } 24 | } 25 | } else { 26 | nameValue = nameResult.value; 27 | } 28 | 29 | return nameValue; 30 | } 31 | 32 | export function fetchTokenSymbol(tokenAddress: Address): string { 33 | let contract = ERC20.bind(tokenAddress); 34 | let contractSymbolBytes = ERC20SymbolBytes.bind(tokenAddress); 35 | 36 | let symbolValue = "unknown"; 37 | let symbolResult = contract.try_symbol(); 38 | if (symbolResult.reverted) { 39 | let symbolResultBytes = contractSymbolBytes.try_symbol(); 40 | if (!symbolResultBytes.reverted) { 41 | if (!isNullBnbValue(symbolResultBytes.value.toHex())) { 42 | symbolValue = symbolResultBytes.value.toString(); 43 | } 44 | } 45 | } else { 46 | symbolValue = symbolResult.value; 47 | } 48 | 49 | return symbolValue; 50 | } 51 | 52 | export function fetchTokenDecimals(tokenAddress: Address): BigInt { 53 | let contract = ERC20.bind(tokenAddress); 54 | let decimalValue = null; 55 | let decimalResult = contract.try_decimals(); 56 | if (!decimalResult.reverted) { 57 | decimalValue = decimalResult.value; 58 | } 59 | return BigInt.fromI32(decimalValue as i32); 60 | } 61 | 62 | export function getOrCreateToken(address: Address): Token { 63 | let token = Token.load(address.toHex()); 64 | if (token === null) { 65 | token = new Token(address.toHex()); 66 | token.name = fetchTokenName(address); 67 | token.symbol = fetchTokenSymbol(address); 68 | token.decimals = fetchTokenDecimals(address); 69 | token.save(); 70 | } 71 | 72 | return token as Token; 73 | } 74 | -------------------------------------------------------------------------------- /subgraphs/smartchef/mappings/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigInt, BigDecimal } from "@graphprotocol/graph-ts"; 3 | 4 | export let ZERO_BI = BigInt.fromI32(0); 5 | export let ONE_BI = BigInt.fromI32(1); 6 | 7 | export let BLACKLISTED_ADDRESSES: string[] = [ 8 | "0x2ba38552ee50c3450427c4afe72f8dd845205a33", // HachiMoon 9 | ]; 10 | 11 | export function exponentToBigDecimal(decimals: BigInt): BigDecimal { 12 | let bd = BigDecimal.fromString("1"); 13 | for (let i = ZERO_BI; i.lt(decimals as BigInt); i = i.plus(ONE_BI)) { 14 | bd = bd.times(BigDecimal.fromString("10")); 15 | } 16 | return bd; 17 | } 18 | 19 | export function convertTokenToDecimal(tokenAmount: BigInt, exchangeDecimals: BigInt): BigDecimal { 20 | if (exchangeDecimals == ZERO_BI) { 21 | return tokenAmount.toBigDecimal(); 22 | } 23 | return tokenAmount.toBigDecimal().div(exponentToBigDecimal(exchangeDecimals)); 24 | } 25 | -------------------------------------------------------------------------------- /subgraphs/smartchef/mappings/utils/smartchef.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigInt } from "@graphprotocol/graph-ts"; 3 | import { SmartChef as SmartChefContract } from "../../generated/SmartChefFactory/SmartChef"; 4 | import { SmartChef } from "../../generated/schema"; 5 | 6 | export let ADDRESS_ZERO = "0x0000000000000000000000000000000000000000"; 7 | 8 | export function fetchStakeToken(smartChefAddress: Address): Address { 9 | let contract = SmartChefContract.bind(smartChefAddress); 10 | let nameValue = Address.fromString(ADDRESS_ZERO); 11 | let nameResult = contract.try_stakedToken(); 12 | if (!nameResult.reverted) { 13 | nameValue = nameResult.value; 14 | } 15 | 16 | return nameValue; 17 | } 18 | 19 | export function fetchRewardToken(smartChefAddress: Address): Address { 20 | let contract = SmartChefContract.bind(smartChefAddress); 21 | let nameValue = Address.fromString(ADDRESS_ZERO); 22 | let nameResult = contract.try_rewardToken(); 23 | if (!nameResult.reverted) { 24 | nameValue = nameResult.value; 25 | } 26 | 27 | return nameValue; 28 | } 29 | 30 | export function fetchStartBlock(smartChefAddress: Address): BigInt { 31 | let contract = SmartChefContract.bind(smartChefAddress); 32 | let decimalValue = BigInt.fromI32(0); 33 | let decimalResult = contract.try_startBlock(); 34 | if (!decimalResult.reverted) { 35 | decimalValue = decimalResult.value; 36 | } 37 | return decimalValue; 38 | } 39 | 40 | export function fetchEndBlock(smartChefAddress: Address): BigInt { 41 | let contract = SmartChefContract.bind(smartChefAddress); 42 | let decimalValue = BigInt.fromI32(0); 43 | let decimalResult = contract.try_bonusEndBlock(); 44 | if (!decimalResult.reverted) { 45 | decimalValue = decimalResult.value; 46 | } 47 | return decimalValue; 48 | } 49 | 50 | export function fetchRewardPerBlock(smartChefAddress: Address): BigInt { 51 | let contract = SmartChefContract.bind(smartChefAddress); 52 | let decimalValue = BigInt.fromI32(0); 53 | let decimalResult = contract.try_rewardPerBlock(); 54 | if (!decimalResult.reverted) { 55 | decimalValue = decimalResult.value; 56 | } 57 | return decimalValue; 58 | } 59 | 60 | export function fetchUserLimit(smartChefAddress: Address): BigInt { 61 | let contract = SmartChefContract.bind(smartChefAddress); 62 | let decimalValue = BigInt.fromI32(0); 63 | let decimalResult = contract.try_poolLimitPerUser(); 64 | if (!decimalResult.reverted) { 65 | decimalValue = decimalResult.value; 66 | } 67 | return decimalValue; 68 | } 69 | 70 | export function getOrCreateSmartChef(address: Address): SmartChef { 71 | let id = address.toHex(); 72 | let smartChef = SmartChef.load(id); 73 | if (smartChef === null) { 74 | smartChef = new SmartChef(id); 75 | } 76 | return smartChef as SmartChef; 77 | } 78 | -------------------------------------------------------------------------------- /subgraphs/smartchef/mappings/utils/user.ts: -------------------------------------------------------------------------------- 1 | import { Address, BigInt } from "@graphprotocol/graph-ts"; 2 | import { User } from "../../generated/schema"; 3 | 4 | export function getOrCreateUser(poolAddress: Address, address: Address): User { 5 | const id = poolAddress.toHex() + "-" + address.toHex(); 6 | 7 | let user = User.load(id); 8 | 9 | if (user === null) { 10 | user = new User(id); 11 | user.stakeAmount = BigInt.fromI32(0); 12 | user.pool = poolAddress.toHex(); 13 | user.address = address; 14 | user.save(); 15 | } 16 | 17 | return user as User; 18 | } 19 | -------------------------------------------------------------------------------- /subgraphs/smartchef/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smartchef", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/smartchef subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/smartchef/schema.graphql: -------------------------------------------------------------------------------- 1 | # Factory 2 | type Factory @entity { 3 | id: ID! 4 | 5 | "Total of SmartChef contracts" 6 | totalSmartChef: BigInt! 7 | } 8 | 9 | # SmartChef 10 | type SmartChef @entity { 11 | id: ID! 12 | 13 | "Token" 14 | stakeToken: Token! 15 | "Token" 16 | earnToken: Token! 17 | 18 | "Start block number" 19 | startBlock: BigInt! 20 | "End block number" 21 | endBlock: BigInt! 22 | 23 | "Reward per block (in earnToken)" 24 | reward: BigDecimal! 25 | 26 | "Limit (if any, in stakeToken)" 27 | limit: BigDecimal 28 | 29 | "Block number" 30 | block: BigInt! 31 | "Block timestamp" 32 | timestamp: BigInt! 33 | 34 | users: [User!]! @derivedFrom(field: "pool") 35 | } 36 | 37 | # Token 38 | type Token @entity { 39 | id: ID! 40 | 41 | "Name" 42 | name: String! 43 | "Symbol" 44 | symbol: String! 45 | "Decimals" 46 | decimals: BigInt! 47 | } 48 | 49 | type User @entity { 50 | "User Address bound to Pool" 51 | id: ID! 52 | address: Bytes! 53 | 54 | pool: SmartChef! 55 | 56 | stakeAmount: BigInt! 57 | stakeToken: Token 58 | } 59 | -------------------------------------------------------------------------------- /subgraphs/smartchef/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: PancakeSwap is a decentralized protocol for automated token exchange on Binance Smart Chain. 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: SmartChefFactory 9 | network: bsc 10 | source: 11 | address: "0x927158Be21Fe3D4da7E96931bb27Fd5059A8CbC2" 12 | abi: SmartChefFactory 13 | startBlock: 7151302 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/factory.ts 19 | entities: 20 | - Factory 21 | - SmartChef 22 | - Token 23 | abis: 24 | - name: SmartChefFactory 25 | file: ./abis/SmartChefFactory.json 26 | - name: SmartChef 27 | file: ./abis/SmartChef.json 28 | - name: ERC20 29 | file: ./abis/ERC20.json 30 | - name: ERC20NameBytes 31 | file: ./abis/ERC20NameBytes.json 32 | - name: ERC20SymbolBytes 33 | file: ./abis/ERC20SymbolBytes.json 34 | eventHandlers: 35 | - event: NewSmartChefContract(indexed address) 36 | handler: handleNewSmartChefContract 37 | - kind: ethereum/contract 38 | name: SmartChefFactoryV2 39 | network: bsc 40 | source: 41 | address: "0xFfF5812C35eC100dF51D5C9842e8cC3fe60f9ad7" 42 | abi: SmartChefFactory 43 | startBlock: 14661669 44 | mapping: 45 | kind: ethereum/events 46 | apiVersion: 0.0.4 47 | language: wasm/assemblyscript 48 | file: ./mappings/factory.ts 49 | entities: 50 | - Factory 51 | - SmartChef 52 | - Token 53 | abis: 54 | - name: SmartChefFactory 55 | file: ./abis/SmartChefFactory.json 56 | - name: SmartChef 57 | file: ./abis/SmartChef.json 58 | - name: ERC20 59 | file: ./abis/ERC20.json 60 | - name: ERC20NameBytes 61 | file: ./abis/ERC20NameBytes.json 62 | - name: ERC20SymbolBytes 63 | file: ./abis/ERC20SymbolBytes.json 64 | eventHandlers: 65 | - event: NewSmartChefContract(indexed address) 66 | handler: handleNewSmartChefContractV2 67 | templates: 68 | - name: SmartChefInitializable 69 | kind: ethereum/contract 70 | network: bsc 71 | source: 72 | abi: SmartChef 73 | mapping: 74 | kind: ethereum/events 75 | apiVersion: 0.0.4 76 | language: wasm/assemblyscript 77 | file: ./mappings/index.ts 78 | entities: 79 | - SmartChef 80 | - User 81 | abis: 82 | - name: SmartChef 83 | file: ./abis/SmartChef.json 84 | eventHandlers: 85 | - event: Deposit(indexed address,uint256) 86 | handler: handleDeposit 87 | - event: EmergencyWithdraw(indexed address,uint256) 88 | handler: handleEmergencyWithdraw 89 | - event: Withdraw(indexed address,uint256) 90 | handler: handleWithdraw 91 | - event: NewStartAndEndBlocks(uint256,uint256) 92 | handler: handleNewStartAndEndBlocks 93 | - event: NewRewardPerBlock(uint256) 94 | handler: handleNewRewardPerBlock 95 | -------------------------------------------------------------------------------- /subgraphs/timelock/mappings/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigInt } from "@graphprotocol/graph-ts"; 3 | import { Timelock } from "../generated/schema"; 4 | import { CancelTransaction, ExecuteTransaction, QueueTransaction } from "../generated/Timelock/Timelock"; 5 | 6 | export function handleCanceledTransaction(event: CancelTransaction): void { 7 | let timelock = Timelock.load(event.params.txHash.toHex()); 8 | if (timelock !== null) { 9 | timelock.canceledAt = event.block.timestamp; 10 | timelock.canceledBlock = event.block.number; 11 | timelock.canceledHash = event.transaction.hash; 12 | timelock.isCanceled = true; 13 | timelock.save(); 14 | } 15 | } 16 | 17 | export function handleExecutedTransaction(event: ExecuteTransaction): void { 18 | let timelock = Timelock.load(event.params.txHash.toHex()); 19 | if (timelock !== null) { 20 | timelock.executedAt = event.block.timestamp; 21 | timelock.executedBlock = event.block.number; 22 | timelock.executedHash = event.transaction.hash; 23 | timelock.isExecuted = true; 24 | timelock.save(); 25 | } 26 | } 27 | 28 | export function handleQueuedTransaction(event: QueueTransaction): void { 29 | let timelock = Timelock.load(event.params.txHash.toHex()); 30 | if (timelock === null) { 31 | timelock = new Timelock(event.params.txHash.toHex()); 32 | timelock.target = event.params.target; 33 | timelock.signature = event.params.signature; 34 | timelock.data = event.params.data; 35 | timelock.value = event.params.value; 36 | timelock.eta = event.params.eta; 37 | timelock.createdAt = event.block.timestamp; 38 | timelock.createdBlock = event.block.number; 39 | timelock.createdHash = event.transaction.hash; 40 | timelock.expiresAt = event.params.eta.plus(BigInt.fromI32(14 * 86400)); 41 | timelock.isExecuted = false; 42 | timelock.isCanceled = false; 43 | timelock.save(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /subgraphs/timelock/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "timelock", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/timelock subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/timelock/schema.graphql: -------------------------------------------------------------------------------- 1 | type Timelock @entity { 2 | id: ID! 3 | 4 | target: Bytes! 5 | signature: String! 6 | data: Bytes! 7 | value: BigInt! 8 | eta: BigInt! 9 | 10 | # Queued 11 | createdAt: BigInt! 12 | createdBlock: BigInt! 13 | createdHash: Bytes! 14 | expiresAt: BigInt! 15 | 16 | # Executed 17 | executedAt: BigInt 18 | executedBlock: BigInt 19 | executedHash: Bytes 20 | isExecuted: Boolean! 21 | 22 | # Cancelled 23 | canceledAt: BigInt 24 | canceledBlock: BigInt 25 | canceledHash: Bytes 26 | isCanceled: Boolean! 27 | } 28 | -------------------------------------------------------------------------------- /subgraphs/timelock/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: PancakeSwap Timelock 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: Timelock 9 | network: bsc 10 | source: 11 | address: '0xA1f482Dc58145Ba2210bC21878Ca34000E2e8fE4' 12 | abi: Timelock 13 | startBlock: 704262 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/index.ts 19 | entities: 20 | - Timelock 21 | abis: 22 | - name: Timelock 23 | file: ./abis/Timelock.json 24 | eventHandlers: 25 | - event: CancelTransaction(indexed bytes32,indexed address,uint256,string,bytes,uint256) 26 | handler: handleCanceledTransaction 27 | - event: ExecuteTransaction(indexed bytes32,indexed address,uint256,string,bytes,uint256) 28 | handler: handleExecutedTransaction 29 | - event: QueueTransaction(indexed bytes32,indexed address,uint256,string,bytes,uint256) 30 | handler: handleQueuedTransaction 31 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v1/abis/Factory.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_feeToSetter", 7 | "type": "address" 8 | } 9 | ], 10 | "payable": false, 11 | "stateMutability": "nonpayable", 12 | "type": "constructor" 13 | }, 14 | { 15 | "anonymous": false, 16 | "inputs": [ 17 | { 18 | "indexed": true, 19 | "internalType": "address", 20 | "name": "token0", 21 | "type": "address" 22 | }, 23 | { 24 | "indexed": true, 25 | "internalType": "address", 26 | "name": "token1", 27 | "type": "address" 28 | }, 29 | { 30 | "indexed": false, 31 | "internalType": "address", 32 | "name": "pair", 33 | "type": "address" 34 | }, 35 | { 36 | "indexed": false, 37 | "internalType": "uint256", 38 | "name": "", 39 | "type": "uint256" 40 | } 41 | ], 42 | "name": "PairCreated", 43 | "type": "event" 44 | }, 45 | { 46 | "constant": true, 47 | "inputs": [], 48 | "name": "INIT_CODE_PAIR_HASH", 49 | "outputs": [ 50 | { 51 | "internalType": "bytes32", 52 | "name": "", 53 | "type": "bytes32" 54 | } 55 | ], 56 | "payable": false, 57 | "stateMutability": "view", 58 | "type": "function" 59 | }, 60 | { 61 | "constant": true, 62 | "inputs": [ 63 | { 64 | "internalType": "uint256", 65 | "name": "", 66 | "type": "uint256" 67 | } 68 | ], 69 | "name": "allPairs", 70 | "outputs": [ 71 | { 72 | "internalType": "address", 73 | "name": "", 74 | "type": "address" 75 | } 76 | ], 77 | "payable": false, 78 | "stateMutability": "view", 79 | "type": "function" 80 | }, 81 | { 82 | "constant": true, 83 | "inputs": [], 84 | "name": "allPairsLength", 85 | "outputs": [ 86 | { 87 | "internalType": "uint256", 88 | "name": "", 89 | "type": "uint256" 90 | } 91 | ], 92 | "payable": false, 93 | "stateMutability": "view", 94 | "type": "function" 95 | }, 96 | { 97 | "constant": false, 98 | "inputs": [ 99 | { 100 | "internalType": "address", 101 | "name": "tokenA", 102 | "type": "address" 103 | }, 104 | { 105 | "internalType": "address", 106 | "name": "tokenB", 107 | "type": "address" 108 | } 109 | ], 110 | "name": "createPair", 111 | "outputs": [ 112 | { 113 | "internalType": "address", 114 | "name": "pair", 115 | "type": "address" 116 | } 117 | ], 118 | "payable": false, 119 | "stateMutability": "nonpayable", 120 | "type": "function" 121 | }, 122 | { 123 | "constant": true, 124 | "inputs": [], 125 | "name": "feeTo", 126 | "outputs": [ 127 | { 128 | "internalType": "address", 129 | "name": "", 130 | "type": "address" 131 | } 132 | ], 133 | "payable": false, 134 | "stateMutability": "view", 135 | "type": "function" 136 | }, 137 | { 138 | "constant": true, 139 | "inputs": [], 140 | "name": "feeToSetter", 141 | "outputs": [ 142 | { 143 | "internalType": "address", 144 | "name": "", 145 | "type": "address" 146 | } 147 | ], 148 | "payable": false, 149 | "stateMutability": "view", 150 | "type": "function" 151 | }, 152 | { 153 | "constant": true, 154 | "inputs": [ 155 | { 156 | "internalType": "address", 157 | "name": "", 158 | "type": "address" 159 | }, 160 | { 161 | "internalType": "address", 162 | "name": "", 163 | "type": "address" 164 | } 165 | ], 166 | "name": "getPair", 167 | "outputs": [ 168 | { 169 | "internalType": "address", 170 | "name": "", 171 | "type": "address" 172 | } 173 | ], 174 | "payable": false, 175 | "stateMutability": "view", 176 | "type": "function" 177 | }, 178 | { 179 | "constant": false, 180 | "inputs": [ 181 | { 182 | "internalType": "address", 183 | "name": "_feeTo", 184 | "type": "address" 185 | } 186 | ], 187 | "name": "setFeeTo", 188 | "outputs": [], 189 | "payable": false, 190 | "stateMutability": "nonpayable", 191 | "type": "function" 192 | }, 193 | { 194 | "constant": false, 195 | "inputs": [ 196 | { 197 | "internalType": "address", 198 | "name": "_feeToSetter", 199 | "type": "address" 200 | } 201 | ], 202 | "name": "setFeeToSetter", 203 | "outputs": [], 204 | "payable": false, 205 | "stateMutability": "nonpayable", 206 | "type": "function" 207 | } 208 | ] 209 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v1/mappings/competition.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigInt, ethereum, log } from "@graphprotocol/graph-ts"; 3 | import { Bundle, Competition, Team, User } from "../generated/schema"; 4 | import { Pair as PairTemplate } from "../generated/templates"; 5 | import { NewCompetitionStatus, UserRegister } from "../generated/TradingCompetitionV1/TradingCompetitionV1"; 6 | import { BD_ZERO, BI_ONE, BI_ZERO, getBnbPriceInUSD, TRACKED_PAIRS } from "./utils"; 7 | 8 | /** 9 | * BLOCK 10 | */ 11 | 12 | export function handleBlock(event: ethereum.Block): void { 13 | // Fail safe condition in case the bundle has already been created. 14 | let bundle = Bundle.load("1"); 15 | if (bundle === null) { 16 | bundle = new Bundle("1"); 17 | bundle.bnbPrice = BD_ZERO; 18 | bundle.block = BI_ZERO; 19 | bundle.save(); 20 | } 21 | bundle.bnbPrice = getBnbPriceInUSD(); 22 | bundle.block = event.number; 23 | bundle.save(); 24 | } 25 | 26 | /** 27 | * COMPETITION 28 | */ 29 | 30 | export function handleUserRegister(event: UserRegister): void { 31 | // Fail safe condition in case the competition has already been created. 32 | let competition = Competition.load("1"); 33 | if (competition === null) { 34 | competition = new Competition("1"); 35 | competition.status = BI_ZERO; // Registration 36 | competition.userCount = BI_ZERO; 37 | competition.volumeUSD = BD_ZERO; 38 | competition.volumeBNB = BD_ZERO; 39 | competition.txCount = BI_ZERO; 40 | competition.save(); 41 | } 42 | competition.userCount = competition.userCount.plus(BI_ONE); 43 | competition.save(); 44 | 45 | // Fail safe condition in case the team has already been created. 46 | let team = Team.load(event.params.teamId.toString()); // Use `String` instead of `hex` to make the reconciliation simpler. 47 | if (team === null) { 48 | team = new Team(event.params.teamId.toString()); 49 | team.userCount = BI_ZERO; 50 | team.volumeUSD = BD_ZERO; 51 | team.volumeBNB = BD_ZERO; 52 | team.txCount = BI_ZERO; 53 | team.save(); 54 | } 55 | team.userCount = team.userCount.plus(BI_ONE); 56 | team.save(); 57 | 58 | // Fail safe condition in case the user has already been created. 59 | let user = User.load(event.params.userAddress.toHex()); 60 | if (user === null) { 61 | user = new User(event.params.userAddress.toHex()); 62 | user.competition = competition.id; 63 | user.team = team.id; 64 | user.block = event.block.number; 65 | user.volumeUSD = BD_ZERO; 66 | user.volumeBNB = BD_ZERO; 67 | user.txCount = BI_ZERO; 68 | user.save(); 69 | } 70 | } 71 | 72 | export function handleNewCompetitionStatus(event: NewCompetitionStatus): void { 73 | // Fail safe condition in case the competition has already been created. 74 | let competition = Competition.load("1"); 75 | if (competition === null) { 76 | competition = new Competition("1"); 77 | competition.status = BI_ZERO; // Registration 78 | competition.userCount = BI_ZERO; 79 | competition.volumeUSD = BD_ZERO; 80 | competition.volumeBNB = BD_ZERO; 81 | competition.txCount = BI_ZERO; 82 | competition.save(); 83 | } 84 | competition.status = BigInt.fromI32(event.params.status); 85 | competition.save(); 86 | 87 | // Competition has opened, trigger PairCreated to follow `Swap` events. 88 | if (BigInt.fromI32(event.params.status).equals(BI_ONE)) { 89 | TRACKED_PAIRS.forEach((address: string) => { 90 | PairTemplate.create(Address.fromString(address)); 91 | 92 | log.info("Created pair with address {}.", [address]); 93 | }); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v1/mappings/pair.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigDecimal, log } from "@graphprotocol/graph-ts"; 3 | import { Bundle, Competition, Team, User } from "../generated/schema"; 4 | import { Swap } from "../generated/templates/Pair/Pair"; 5 | import { BD_1E18, BI_ONE, TRACKED_PAIRS } from "./utils"; 6 | 7 | /** 8 | * SWAP 9 | */ 10 | 11 | export function handleSwap(event: Swap): void { 12 | let competition = Competition.load("1"); 13 | // Competition is not in progress, ignoring trade. 14 | if (competition.status.notEqual(BI_ONE)) { 15 | log.info("Competition is not in progress, ignoring trade; status: {}", [competition.status.toString()]); 16 | return; 17 | } 18 | 19 | // User is not registered for the competition, skipping. 20 | let user = User.load(event.transaction.from.toHex()); 21 | if (user === null) { 22 | log.info("User is not registered, ignoring trade; user: {}", [event.transaction.from.toHex()]); 23 | return; 24 | } 25 | 26 | // We load other entities as the trade is doomed valid and competition is in progress. 27 | let bundle = Bundle.load("1"); 28 | let team = Team.load(user.team); 29 | 30 | let bnbIN: BigDecimal; 31 | let bnbOUT: BigDecimal; 32 | 33 | if (event.address.equals(Address.fromString(TRACKED_PAIRS[0]))) { 34 | bnbIN = event.params.amount0In.toBigDecimal().div(BD_1E18); 35 | bnbOUT = event.params.amount0Out.toBigDecimal().div(BD_1E18); 36 | } else { 37 | bnbIN = event.params.amount1In.toBigDecimal().div(BD_1E18); 38 | bnbOUT = event.params.amount1Out.toBigDecimal().div(BD_1E18); 39 | } 40 | 41 | let volumeBNB = bnbOUT.plus(bnbIN); 42 | let volumeUSD = volumeBNB.times(bundle.bnbPrice); 43 | 44 | log.info("Volume: {} for {} BNB, or {} USD", [ 45 | event.transaction.from.toHex(), 46 | volumeBNB.toString(), 47 | volumeUSD.toString(), 48 | ]); 49 | 50 | user.volumeUSD = user.volumeUSD.plus(volumeUSD); 51 | user.volumeBNB = user.volumeBNB.plus(volumeBNB); 52 | user.txCount = user.txCount.plus(BI_ONE); 53 | user.save(); 54 | 55 | // Team statistics. 56 | team.volumeUSD = team.volumeUSD.plus(volumeUSD); 57 | team.volumeBNB = team.volumeBNB.plus(volumeBNB); 58 | team.txCount = team.txCount.plus(BI_ONE); 59 | team.save(); 60 | 61 | // Competition statistics. 62 | competition.volumeUSD = competition.volumeUSD.plus(volumeUSD); 63 | competition.volumeBNB = competition.volumeBNB.plus(volumeBNB); 64 | competition.txCount = competition.txCount.plus(BI_ONE); 65 | competition.save(); 66 | } 67 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v1/mappings/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts"; 3 | import { Pair } from "../../generated/templates/Pair/Pair"; 4 | 5 | export let BI_ZERO = BigInt.fromI32(0); 6 | export let BI_ONE = BigInt.fromI32(1); 7 | export let BD_ZERO = BigDecimal.fromString("0"); 8 | export let BD_1E18 = BigDecimal.fromString("1e18"); 9 | 10 | export let TRACKED_PAIRS: string[] = [ 11 | "0x1b96b92314c44b159149f7e0303511fb2fc4774f", // WBNB/BUSD 12 | "0xa527a61703d82139f8a06bc30097cc9caa2df5a6", // CAKE/WBNB 13 | "0x70d8929d04b60af4fb9b58713ebcf18765ade422", // ETH/WBNB 14 | "0x7561eee90e24f3b348e1087a005f78b4c8453524", // BTCB/WBNB 15 | ]; 16 | 17 | export function getBnbPriceInUSD(): BigDecimal { 18 | // Bind WBNB/BUSD contract to query the pair. 19 | let pairContract = Pair.bind(Address.fromString(TRACKED_PAIRS[0])); 20 | 21 | // Fail-safe call to get BNB price as BUSD. 22 | let reserves = pairContract.try_getReserves(); 23 | if (!reserves.reverted) { 24 | let reserve0 = reserves.value.value0.toBigDecimal().div(BD_1E18); 25 | let reserve1 = reserves.value.value1.toBigDecimal().div(BD_1E18); 26 | 27 | if (reserve0.notEqual(BD_ZERO)) { 28 | return reserve1.div(reserve0); 29 | } 30 | } 31 | 32 | return BD_ZERO; 33 | } 34 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trading-competition-v1", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/trading-competition-v1 subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v1/schema.graphql: -------------------------------------------------------------------------------- 1 | type Bundle @entity { 2 | id: ID! 3 | 4 | # Price in USD for BNB, derived from WBNB/BUSD pair 5 | bnbPrice: BigDecimal! 6 | 7 | # Block number 8 | block: BigInt! 9 | } 10 | 11 | type Competition @entity { 12 | id: ID! 13 | 14 | # Status 15 | status: BigInt! 16 | 17 | # Users 18 | userCount: BigInt! 19 | users: [User!]! @derivedFrom(field: "competition") 20 | 21 | # Volume 22 | volumeUSD: BigDecimal! 23 | volumeBNB: BigDecimal! 24 | 25 | # Transactions count 26 | txCount: BigInt! 27 | } 28 | 29 | type Team @entity { 30 | id: ID! # address 31 | 32 | # Users 33 | userCount: BigInt! 34 | users: [User!]! @derivedFrom(field: "team") 35 | 36 | # Volume 37 | volumeUSD: BigDecimal! 38 | volumeBNB: BigDecimal! 39 | 40 | # Transactions count 41 | txCount: BigInt! 42 | } 43 | 44 | type User @entity { 45 | id: ID! # address 46 | 47 | # Competition 48 | competition: Competition! 49 | 50 | # Team 51 | team: Team! 52 | 53 | # Block number 54 | block: BigInt! 55 | 56 | # Volume 57 | volumeUSD: BigDecimal! 58 | volumeBNB: BigDecimal! 59 | 60 | # Transactions count 61 | txCount: BigInt! 62 | } 63 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v1/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Pancake Trading Competition V1 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: TradingCompetitionV1 9 | network: bsc 10 | source: 11 | address: '0xd718baa0B1F4f70dcC8458154042120FFE0DEFFA' 12 | abi: TradingCompetitionV1 13 | startBlock: 6214239 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/competition.ts 19 | entities: 20 | - Bundle 21 | - Competition 22 | - Team 23 | - User 24 | abis: 25 | - name: TradingCompetitionV1 26 | file: ./abis/TradingCompetitionV1.json 27 | - name: Factory 28 | file: ./abis/Factory.json 29 | - name: Pair 30 | file: ./abis/Pair.json 31 | blockHandlers: 32 | - handler: handleBlock 33 | eventHandlers: 34 | - event: UserRegister(address,uint256) 35 | handler: handleUserRegister 36 | - event: NewCompetitionStatus(uint8) 37 | handler: handleNewCompetitionStatus 38 | templates: 39 | - kind: ethereum/contract 40 | name: Pair 41 | network: bsc 42 | source: 43 | abi: Pair 44 | mapping: 45 | kind: ethereum/events 46 | apiVersion: 0.0.4 47 | language: wasm/assemblyscript 48 | file: ./mappings/pair.ts 49 | entities: 50 | - Bundle 51 | - Competition 52 | - Team 53 | - User 54 | abis: 55 | - name: Factory 56 | file: ./abis/Factory.json 57 | - name: Pair 58 | file: ./abis/Pair.json 59 | eventHandlers: 60 | - event: Swap(indexed address,uint256,uint256,uint256,uint256,indexed address) 61 | handler: handleSwap 62 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v2/abis/Factory.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_feeToSetter", 7 | "type": "address" 8 | } 9 | ], 10 | "payable": false, 11 | "stateMutability": "nonpayable", 12 | "type": "constructor" 13 | }, 14 | { 15 | "anonymous": false, 16 | "inputs": [ 17 | { 18 | "indexed": true, 19 | "internalType": "address", 20 | "name": "token0", 21 | "type": "address" 22 | }, 23 | { 24 | "indexed": true, 25 | "internalType": "address", 26 | "name": "token1", 27 | "type": "address" 28 | }, 29 | { 30 | "indexed": false, 31 | "internalType": "address", 32 | "name": "pair", 33 | "type": "address" 34 | }, 35 | { 36 | "indexed": false, 37 | "internalType": "uint256", 38 | "name": "", 39 | "type": "uint256" 40 | } 41 | ], 42 | "name": "PairCreated", 43 | "type": "event" 44 | }, 45 | { 46 | "constant": true, 47 | "inputs": [], 48 | "name": "INIT_CODE_PAIR_HASH", 49 | "outputs": [ 50 | { 51 | "internalType": "bytes32", 52 | "name": "", 53 | "type": "bytes32" 54 | } 55 | ], 56 | "payable": false, 57 | "stateMutability": "view", 58 | "type": "function" 59 | }, 60 | { 61 | "constant": true, 62 | "inputs": [ 63 | { 64 | "internalType": "uint256", 65 | "name": "", 66 | "type": "uint256" 67 | } 68 | ], 69 | "name": "allPairs", 70 | "outputs": [ 71 | { 72 | "internalType": "address", 73 | "name": "", 74 | "type": "address" 75 | } 76 | ], 77 | "payable": false, 78 | "stateMutability": "view", 79 | "type": "function" 80 | }, 81 | { 82 | "constant": true, 83 | "inputs": [], 84 | "name": "allPairsLength", 85 | "outputs": [ 86 | { 87 | "internalType": "uint256", 88 | "name": "", 89 | "type": "uint256" 90 | } 91 | ], 92 | "payable": false, 93 | "stateMutability": "view", 94 | "type": "function" 95 | }, 96 | { 97 | "constant": false, 98 | "inputs": [ 99 | { 100 | "internalType": "address", 101 | "name": "tokenA", 102 | "type": "address" 103 | }, 104 | { 105 | "internalType": "address", 106 | "name": "tokenB", 107 | "type": "address" 108 | } 109 | ], 110 | "name": "createPair", 111 | "outputs": [ 112 | { 113 | "internalType": "address", 114 | "name": "pair", 115 | "type": "address" 116 | } 117 | ], 118 | "payable": false, 119 | "stateMutability": "nonpayable", 120 | "type": "function" 121 | }, 122 | { 123 | "constant": true, 124 | "inputs": [], 125 | "name": "feeTo", 126 | "outputs": [ 127 | { 128 | "internalType": "address", 129 | "name": "", 130 | "type": "address" 131 | } 132 | ], 133 | "payable": false, 134 | "stateMutability": "view", 135 | "type": "function" 136 | }, 137 | { 138 | "constant": true, 139 | "inputs": [], 140 | "name": "feeToSetter", 141 | "outputs": [ 142 | { 143 | "internalType": "address", 144 | "name": "", 145 | "type": "address" 146 | } 147 | ], 148 | "payable": false, 149 | "stateMutability": "view", 150 | "type": "function" 151 | }, 152 | { 153 | "constant": true, 154 | "inputs": [ 155 | { 156 | "internalType": "address", 157 | "name": "", 158 | "type": "address" 159 | }, 160 | { 161 | "internalType": "address", 162 | "name": "", 163 | "type": "address" 164 | } 165 | ], 166 | "name": "getPair", 167 | "outputs": [ 168 | { 169 | "internalType": "address", 170 | "name": "", 171 | "type": "address" 172 | } 173 | ], 174 | "payable": false, 175 | "stateMutability": "view", 176 | "type": "function" 177 | }, 178 | { 179 | "constant": false, 180 | "inputs": [ 181 | { 182 | "internalType": "address", 183 | "name": "_feeTo", 184 | "type": "address" 185 | } 186 | ], 187 | "name": "setFeeTo", 188 | "outputs": [], 189 | "payable": false, 190 | "stateMutability": "nonpayable", 191 | "type": "function" 192 | }, 193 | { 194 | "constant": false, 195 | "inputs": [ 196 | { 197 | "internalType": "address", 198 | "name": "_feeToSetter", 199 | "type": "address" 200 | } 201 | ], 202 | "name": "setFeeToSetter", 203 | "outputs": [], 204 | "payable": false, 205 | "stateMutability": "nonpayable", 206 | "type": "function" 207 | } 208 | ] 209 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v2/mappings/competition.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigInt, ethereum, log } from "@graphprotocol/graph-ts"; 3 | import { Bundle, Competition, Team, User } from "../generated/schema"; 4 | import { Pair as PairTemplate } from "../generated/templates"; 5 | import { NewCompetitionStatus, UserRegister } from "../generated/TradingCompetitionV2/TradingCompetitionV2"; 6 | import { 7 | BD_ZERO, 8 | BI_ONE, 9 | BI_ZERO, 10 | getBnbPriceInUSD, 11 | TRACKED_TOKEN_BUSD_PAIRS, 12 | TRACKED_TOKEN_BNB_PAIRS, 13 | WBNB_BUSD, 14 | } from "./utils"; 15 | 16 | /** 17 | * BLOCK 18 | */ 19 | 20 | export function handleBlock(event: ethereum.Block): void { 21 | // Fail safe condition in case the bundle has already been created. 22 | let bundle = Bundle.load("1"); 23 | if (bundle === null) { 24 | bundle = new Bundle("1"); 25 | bundle.bnbPrice = BD_ZERO; 26 | bundle.block = BI_ZERO; 27 | bundle.save(); 28 | } 29 | bundle.bnbPrice = getBnbPriceInUSD(); 30 | bundle.block = event.number; 31 | bundle.save(); 32 | } 33 | 34 | /** 35 | * COMPETITION 36 | */ 37 | 38 | export function handleUserRegister(event: UserRegister): void { 39 | // Fail safe condition in case the competition has already been created. 40 | let competition = Competition.load(event.params.competitionId.toString()); 41 | if (competition === null) { 42 | competition = new Competition(event.params.competitionId.toString()); 43 | competition.status = BI_ZERO; // Registration 44 | competition.userCount = BI_ZERO; 45 | competition.volumeUSD = BD_ZERO; 46 | competition.volumeBNB = BD_ZERO; 47 | competition.txCount = BI_ZERO; 48 | competition.save(); 49 | } 50 | competition.userCount = competition.userCount.plus(BI_ONE); 51 | competition.save(); 52 | 53 | // Fail safe condition in case the team has already been created. 54 | let team = Team.load(event.params.teamId.toString()); // Use `String` instead of `hex` to make the reconciliation simpler. 55 | if (team === null) { 56 | team = new Team(event.params.teamId.toString()); 57 | team.userCount = BI_ZERO; 58 | team.volumeUSD = BD_ZERO; 59 | team.volumeBNB = BD_ZERO; 60 | team.txCount = BI_ZERO; 61 | team.save(); 62 | } 63 | team.userCount = team.userCount.plus(BI_ONE); 64 | team.save(); 65 | 66 | // Fail safe condition in case the user has already been created. 67 | let user = User.load(event.params.userAddress.toHex()); 68 | if (user === null) { 69 | user = new User(event.params.userAddress.toHex()); 70 | user.competition = competition.id; 71 | user.team = team.id; 72 | user.block = event.block.number; 73 | user.volumeUSD = BD_ZERO; 74 | user.volumeBNB = BD_ZERO; 75 | user.txCount = BI_ZERO; 76 | user.save(); 77 | } 78 | } 79 | 80 | export function handleNewCompetitionStatus(event: NewCompetitionStatus): void { 81 | // Fail safe condition in case the competition has already been created. 82 | let competition = Competition.load(event.params.competitionId.toString()); 83 | if (competition === null) { 84 | competition = new Competition(event.params.competitionId.toString()); 85 | competition.status = BI_ZERO; // Registration 86 | competition.userCount = BI_ZERO; 87 | competition.volumeUSD = BD_ZERO; 88 | competition.volumeBNB = BD_ZERO; 89 | competition.txCount = BI_ZERO; 90 | competition.save(); 91 | } 92 | competition.status = BigInt.fromI32(event.params.status); 93 | competition.save(); 94 | 95 | // Competition has opened, trigger PairCreated to follow `Swap` events. 96 | if (BigInt.fromI32(event.params.status).equals(BI_ONE)) { 97 | PairTemplate.create(Address.fromString(WBNB_BUSD)); 98 | 99 | log.info("Created pair with address {}.", [WBNB_BUSD]); 100 | TRACKED_TOKEN_BUSD_PAIRS.forEach((address: string) => { 101 | PairTemplate.create(Address.fromString(address)); 102 | 103 | log.info("Created pair with address {}.", [address]); 104 | }); 105 | TRACKED_TOKEN_BNB_PAIRS.forEach((address: string) => { 106 | PairTemplate.create(Address.fromString(address)); 107 | 108 | log.info("Created pair with address {}.", [address]); 109 | }); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v2/mappings/pair.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigDecimal, log } from "@graphprotocol/graph-ts"; 3 | import { Bundle, Competition, Team, User, PairStats } from "../generated/schema"; 4 | import { Swap } from "../generated/templates/Pair/Pair"; 5 | import { BD_1E18, BD_ZERO, BI_ONE, TRACKED_TOKEN_BNB_PAIRS, TRACKED_TOKEN_BUSD_PAIRS } from "./utils"; 6 | 7 | /** 8 | * SWAP 9 | */ 10 | 11 | export function handleSwap(event: Swap): void { 12 | let competition = Competition.load("2"); 13 | // Competition is not in progress, ignoring trade. 14 | if (competition.status.notEqual(BI_ONE)) { 15 | log.info("Competition is not in progress, ignoring trade; status: {}", [competition.status.toString()]); 16 | return; 17 | } 18 | 19 | // User is not registered for the competition, skipping. 20 | let user = User.load(event.transaction.from.toHex()); 21 | if (user === null) { 22 | log.info("User is not registered, ignoring trade; user: {}", [event.transaction.from.toHex()]); 23 | return; 24 | } 25 | 26 | // We load other entities as the trade is doomed valid and competition is in progress. 27 | let bundle = Bundle.load("1"); 28 | let team = Team.load(user.team); 29 | 30 | let bnbIN: BigDecimal; 31 | let bnbOUT: BigDecimal; 32 | 33 | let busdIN: BigDecimal; 34 | let busdOUT: BigDecimal; 35 | 36 | log.info("Pair info: {}, amount0In: {}, amount1In: {}, amount0Out: {}, amount1Out: {}", [ 37 | event.address.toHex(), 38 | event.params.amount0In.toString(), 39 | event.params.amount1In.toString(), 40 | event.params.amount0Out.toString(), 41 | event.params.amount1Out.toString(), 42 | ]); 43 | 44 | if (TRACKED_TOKEN_BUSD_PAIRS.includes(event.address.toHex())) { 45 | busdIN = event.params.amount1In.toBigDecimal().div(BD_1E18); 46 | busdOUT = event.params.amount1Out.toBigDecimal().div(BD_1E18); 47 | log.info("Pair found: {}, busdIN: {}, busdOUT: {}", [event.address.toHex(), busdIN.toString(), busdOUT.toString()]); 48 | } else if (TRACKED_TOKEN_BNB_PAIRS.includes(event.address.toHex())) { 49 | bnbIN = event.params.amount1In.toBigDecimal().div(BD_1E18); 50 | bnbOUT = event.params.amount1Out.toBigDecimal().div(BD_1E18); 51 | log.info("Pair found: {}, bnbIN: {}, bnbOUT: {}", [event.address.toHex(), bnbIN.toString(), bnbOUT.toString()]); 52 | } else { 53 | log.info("Pair not tracked: {}", [event.address.toHex()]); 54 | return; 55 | } 56 | 57 | let volumeBNB: BigDecimal; 58 | let volumeUSD: BigDecimal; 59 | if (bnbIN) { 60 | volumeBNB = bnbOUT.plus(bnbIN); 61 | volumeUSD = volumeBNB.times(bundle.bnbPrice); 62 | } else { 63 | volumeUSD = busdIN.plus(busdOUT); 64 | volumeBNB = volumeUSD.div(bundle.bnbPrice); 65 | } 66 | 67 | log.info("Volume: {} for {} BNB, or {} USD", [ 68 | event.transaction.from.toHex(), 69 | volumeBNB.toString(), 70 | volumeUSD.toString(), 71 | ]); 72 | 73 | // Fail safe condition in case the pairStats has already been created. 74 | let pairStats = PairStats.load(event.address.toHex()); 75 | if (pairStats === null) { 76 | pairStats = new PairStats(event.address.toHex()); 77 | pairStats.volumeUSD = BD_ZERO; 78 | pairStats.volumeBNB = BD_ZERO; 79 | pairStats.save(); 80 | } 81 | pairStats.volumeUSD = pairStats.volumeUSD.plus(volumeUSD); 82 | pairStats.volumeBNB = pairStats.volumeBNB.plus(volumeBNB); 83 | pairStats.save(); 84 | 85 | user.volumeUSD = user.volumeUSD.plus(volumeUSD); 86 | user.volumeBNB = user.volumeBNB.plus(volumeBNB); 87 | user.txCount = user.txCount.plus(BI_ONE); 88 | user.save(); 89 | 90 | // Team statistics. 91 | team.volumeUSD = team.volumeUSD.plus(volumeUSD); 92 | team.volumeBNB = team.volumeBNB.plus(volumeBNB); 93 | team.txCount = team.txCount.plus(BI_ONE); 94 | team.save(); 95 | 96 | // Competition statistics. 97 | competition.volumeUSD = competition.volumeUSD.plus(volumeUSD); 98 | competition.volumeBNB = competition.volumeBNB.plus(volumeBNB); 99 | competition.txCount = competition.txCount.plus(BI_ONE); 100 | competition.save(); 101 | } 102 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v2/mappings/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts"; 3 | import { Pair } from "../../generated/templates/Pair/Pair"; 4 | 5 | export let BI_ZERO = BigInt.fromI32(0); 6 | export let BI_ONE = BigInt.fromI32(1); 7 | export let BD_ZERO = BigDecimal.fromString("0"); 8 | export let BD_1E18 = BigDecimal.fromString("1e18"); 9 | 10 | export const WBNB_BUSD = "0x58F876857a02D6762E0101bb5C46A8c1ED44Dc16"; 11 | 12 | export let TRACKED_TOKEN_BNB_PAIRS: string[] = [ 13 | "0x11c0b2bb4fbb430825d07507a9e24e4c32f7704d", // LAZIO/BNB 14 | "0x0a292e96abb35297786a38fdd67dc4f82689e670", // PORTO/BNB 15 | "0x06043b346450bbcfde066ebc39fdc264fdffed74", // SANTOS/BNB 16 | "0x0ed7e52944161450477ee417de9cd3a859b14fd0", // CAKE/BNB 17 | ]; 18 | 19 | export let TRACKED_TOKEN_BUSD_PAIRS: string[] = [ 20 | "0xdc49a4d0ccb2615a4d44d908d92dd79866d12ed5", // LAZIO/BUSD 21 | "0xc9e0b6eb78ff5c28fbb112f4f7cca7cfbc03e4ec", // PORTO/BUSD 22 | "0x2ac135e73babdd747e18dcfc14583c9cbe624085", // SANTOS/BUSD 23 | "0x804678fa97d91b974ec2af3c843270886528a9e6", // CAKE/BUSD 24 | ]; 25 | 26 | export function getBnbPriceInUSD(): BigDecimal { 27 | // Bind WBNB/BUSD contract to query the pair. 28 | let pairContract = Pair.bind(Address.fromString(WBNB_BUSD)); 29 | 30 | // Fail-safe call to get BNB price as BUSD. 31 | let reserves = pairContract.try_getReserves(); 32 | if (!reserves.reverted) { 33 | let reserve0 = reserves.value.value0.toBigDecimal().div(BD_1E18); 34 | let reserve1 = reserves.value.value1.toBigDecimal().div(BD_1E18); 35 | 36 | if (reserve0.notEqual(BD_ZERO)) { 37 | return reserve1.div(reserve0); 38 | } 39 | } 40 | 41 | return BD_ZERO; 42 | } 43 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trading-competition-v2", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/trading-competition-v2 subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v2/schema.graphql: -------------------------------------------------------------------------------- 1 | type Bundle @entity { 2 | id: ID! 3 | 4 | # Price in USD for BNB, derived from WBNB/BUSD pair 5 | bnbPrice: BigDecimal! 6 | 7 | # Block number 8 | block: BigInt! 9 | } 10 | 11 | type Competition @entity { 12 | id: ID! 13 | 14 | # Status 15 | status: BigInt! 16 | 17 | # Users 18 | userCount: BigInt! 19 | users: [User!]! @derivedFrom(field: "competition") 20 | 21 | # Volume 22 | volumeUSD: BigDecimal! 23 | volumeBNB: BigDecimal! 24 | 25 | # Transactions count 26 | txCount: BigInt! 27 | } 28 | 29 | type Team @entity { 30 | id: ID! # address 31 | 32 | # Users 33 | userCount: BigInt! 34 | users: [User!]! @derivedFrom(field: "team") 35 | 36 | # Volume 37 | volumeUSD: BigDecimal! 38 | volumeBNB: BigDecimal! 39 | 40 | # Transactions count 41 | txCount: BigInt! 42 | } 43 | 44 | type User @entity { 45 | id: ID! # address 46 | 47 | # Competition 48 | competition: Competition! 49 | 50 | # Team 51 | team: Team! 52 | 53 | # Block number 54 | block: BigInt! 55 | 56 | # Volume 57 | volumeUSD: BigDecimal! 58 | volumeBNB: BigDecimal! 59 | 60 | # Transactions count 61 | txCount: BigInt! 62 | } 63 | 64 | type PairStats @entity { 65 | id: ID! # address 66 | 67 | # Volume 68 | volumeUSD: BigDecimal! 69 | volumeBNB: BigDecimal! 70 | } -------------------------------------------------------------------------------- /subgraphs/trading-competition/v2/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Pancake Trading Competition V1 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: TradingCompetitionV2 9 | network: bsc 10 | source: 11 | address: '0x9b872C05C38A3563393668839659bA336Cc969B2' 12 | abi: TradingCompetitionV2 13 | startBlock: 13321400 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/competition.ts 19 | entities: 20 | - Bundle 21 | - Competition 22 | - Team 23 | - User 24 | - PairStats 25 | abis: 26 | - name: TradingCompetitionV2 27 | file: ./abis/TradingCompetitionV2.json 28 | - name: Factory 29 | file: ./abis/Factory.json 30 | - name: Pair 31 | file: ./abis/Pair.json 32 | blockHandlers: 33 | - handler: handleBlock 34 | eventHandlers: 35 | - event: UserRegister(address,uint256,uint256) 36 | handler: handleUserRegister 37 | - event: NewCompetitionStatus(uint8,uint256) 38 | handler: handleNewCompetitionStatus 39 | templates: 40 | - kind: ethereum/contract 41 | name: Pair 42 | network: bsc 43 | source: 44 | abi: Pair 45 | mapping: 46 | kind: ethereum/events 47 | apiVersion: 0.0.4 48 | language: wasm/assemblyscript 49 | file: ./mappings/pair.ts 50 | entities: 51 | - Bundle 52 | - Competition 53 | - Team 54 | - User 55 | - PairStats 56 | abis: 57 | - name: Factory 58 | file: ./abis/Factory.json 59 | - name: Pair 60 | file: ./abis/Pair.json 61 | eventHandlers: 62 | - event: Swap(indexed address,uint256,uint256,uint256,uint256,indexed address) 63 | handler: handleSwap 64 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v3/abis/Factory.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_feeToSetter", 7 | "type": "address" 8 | } 9 | ], 10 | "payable": false, 11 | "stateMutability": "nonpayable", 12 | "type": "constructor" 13 | }, 14 | { 15 | "anonymous": false, 16 | "inputs": [ 17 | { 18 | "indexed": true, 19 | "internalType": "address", 20 | "name": "token0", 21 | "type": "address" 22 | }, 23 | { 24 | "indexed": true, 25 | "internalType": "address", 26 | "name": "token1", 27 | "type": "address" 28 | }, 29 | { 30 | "indexed": false, 31 | "internalType": "address", 32 | "name": "pair", 33 | "type": "address" 34 | }, 35 | { 36 | "indexed": false, 37 | "internalType": "uint256", 38 | "name": "", 39 | "type": "uint256" 40 | } 41 | ], 42 | "name": "PairCreated", 43 | "type": "event" 44 | }, 45 | { 46 | "constant": true, 47 | "inputs": [], 48 | "name": "INIT_CODE_PAIR_HASH", 49 | "outputs": [ 50 | { 51 | "internalType": "bytes32", 52 | "name": "", 53 | "type": "bytes32" 54 | } 55 | ], 56 | "payable": false, 57 | "stateMutability": "view", 58 | "type": "function" 59 | }, 60 | { 61 | "constant": true, 62 | "inputs": [ 63 | { 64 | "internalType": "uint256", 65 | "name": "", 66 | "type": "uint256" 67 | } 68 | ], 69 | "name": "allPairs", 70 | "outputs": [ 71 | { 72 | "internalType": "address", 73 | "name": "", 74 | "type": "address" 75 | } 76 | ], 77 | "payable": false, 78 | "stateMutability": "view", 79 | "type": "function" 80 | }, 81 | { 82 | "constant": true, 83 | "inputs": [], 84 | "name": "allPairsLength", 85 | "outputs": [ 86 | { 87 | "internalType": "uint256", 88 | "name": "", 89 | "type": "uint256" 90 | } 91 | ], 92 | "payable": false, 93 | "stateMutability": "view", 94 | "type": "function" 95 | }, 96 | { 97 | "constant": false, 98 | "inputs": [ 99 | { 100 | "internalType": "address", 101 | "name": "tokenA", 102 | "type": "address" 103 | }, 104 | { 105 | "internalType": "address", 106 | "name": "tokenB", 107 | "type": "address" 108 | } 109 | ], 110 | "name": "createPair", 111 | "outputs": [ 112 | { 113 | "internalType": "address", 114 | "name": "pair", 115 | "type": "address" 116 | } 117 | ], 118 | "payable": false, 119 | "stateMutability": "nonpayable", 120 | "type": "function" 121 | }, 122 | { 123 | "constant": true, 124 | "inputs": [], 125 | "name": "feeTo", 126 | "outputs": [ 127 | { 128 | "internalType": "address", 129 | "name": "", 130 | "type": "address" 131 | } 132 | ], 133 | "payable": false, 134 | "stateMutability": "view", 135 | "type": "function" 136 | }, 137 | { 138 | "constant": true, 139 | "inputs": [], 140 | "name": "feeToSetter", 141 | "outputs": [ 142 | { 143 | "internalType": "address", 144 | "name": "", 145 | "type": "address" 146 | } 147 | ], 148 | "payable": false, 149 | "stateMutability": "view", 150 | "type": "function" 151 | }, 152 | { 153 | "constant": true, 154 | "inputs": [ 155 | { 156 | "internalType": "address", 157 | "name": "", 158 | "type": "address" 159 | }, 160 | { 161 | "internalType": "address", 162 | "name": "", 163 | "type": "address" 164 | } 165 | ], 166 | "name": "getPair", 167 | "outputs": [ 168 | { 169 | "internalType": "address", 170 | "name": "", 171 | "type": "address" 172 | } 173 | ], 174 | "payable": false, 175 | "stateMutability": "view", 176 | "type": "function" 177 | }, 178 | { 179 | "constant": false, 180 | "inputs": [ 181 | { 182 | "internalType": "address", 183 | "name": "_feeTo", 184 | "type": "address" 185 | } 186 | ], 187 | "name": "setFeeTo", 188 | "outputs": [], 189 | "payable": false, 190 | "stateMutability": "nonpayable", 191 | "type": "function" 192 | }, 193 | { 194 | "constant": false, 195 | "inputs": [ 196 | { 197 | "internalType": "address", 198 | "name": "_feeToSetter", 199 | "type": "address" 200 | } 201 | ], 202 | "name": "setFeeToSetter", 203 | "outputs": [], 204 | "payable": false, 205 | "stateMutability": "nonpayable", 206 | "type": "function" 207 | } 208 | ] 209 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v3/mappings/competition.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigInt, ethereum, log } from "@graphprotocol/graph-ts"; 3 | import { Bundle, Competition, Team, User } from "../generated/schema"; 4 | import { Pair as PairTemplate } from "../generated/templates"; 5 | import { NewCompetitionStatus, UserRegister } from "../generated/TradingCompetitionV3/TradingCompetitionV3"; 6 | import { 7 | BD_ZERO, 8 | BI_ONE, 9 | BI_ZERO, 10 | getBnbPriceInUSD, 11 | TRACKED_TOKEN_BUSD_PAIRS, 12 | TRACKED_TOKEN_BNB_PAIRS, 13 | WBNB_BUSD, 14 | } from "./utils"; 15 | 16 | /** 17 | * BLOCK 18 | */ 19 | 20 | export function handleBlock(event: ethereum.Block): void { 21 | // Fail safe condition in case the bundle has already been created. 22 | let bundle = Bundle.load("1"); 23 | if (bundle === null) { 24 | bundle = new Bundle("1"); 25 | bundle.bnbPrice = BD_ZERO; 26 | bundle.block = BI_ZERO; 27 | bundle.save(); 28 | } 29 | bundle.bnbPrice = getBnbPriceInUSD(); 30 | bundle.block = event.number; 31 | bundle.save(); 32 | } 33 | 34 | /** 35 | * COMPETITION 36 | */ 37 | 38 | export function handleUserRegister(event: UserRegister): void { 39 | // Fail safe condition in case the competition has already been created. 40 | let competition = Competition.load(event.params.competitionId.toString()); 41 | if (competition === null) { 42 | competition = new Competition(event.params.competitionId.toString()); 43 | competition.status = BI_ZERO; // Registration 44 | competition.userCount = BI_ZERO; 45 | competition.volumeUSD = BD_ZERO; 46 | competition.volumeBNB = BD_ZERO; 47 | competition.txCount = BI_ZERO; 48 | competition.save(); 49 | } 50 | competition.userCount = competition.userCount.plus(BI_ONE); 51 | competition.save(); 52 | 53 | // Fail safe condition in case the team has already been created. 54 | let team = Team.load(event.params.teamId.toString()); // Use `String` instead of `hex` to make the reconciliation simpler. 55 | if (team === null) { 56 | team = new Team(event.params.teamId.toString()); 57 | team.userCount = BI_ZERO; 58 | team.volumeUSD = BD_ZERO; 59 | team.volumeBNB = BD_ZERO; 60 | team.txCount = BI_ZERO; 61 | team.save(); 62 | } 63 | team.userCount = team.userCount.plus(BI_ONE); 64 | team.save(); 65 | 66 | // Fail safe condition in case the user has already been created. 67 | let user = User.load(event.params.userAddress.toHex()); 68 | if (user === null) { 69 | user = new User(event.params.userAddress.toHex()); 70 | user.competition = competition.id; 71 | user.team = team.id; 72 | user.block = event.block.number; 73 | user.volumeUSD = BD_ZERO; 74 | user.volumeBNB = BD_ZERO; 75 | user.moboxVolumeUSD = BD_ZERO; 76 | user.moboxVolumeBNB = BD_ZERO; 77 | user.txCount = BI_ZERO; 78 | user.save(); 79 | } 80 | } 81 | 82 | export function handleNewCompetitionStatus(event: NewCompetitionStatus): void { 83 | // Fail safe condition in case the competition has already been created. 84 | let competition = Competition.load(event.params.competitionId.toString()); 85 | if (competition === null) { 86 | competition = new Competition(event.params.competitionId.toString()); 87 | competition.status = BI_ZERO; // Registration 88 | competition.userCount = BI_ZERO; 89 | competition.volumeUSD = BD_ZERO; 90 | competition.volumeBNB = BD_ZERO; 91 | competition.txCount = BI_ZERO; 92 | competition.save(); 93 | } 94 | competition.status = BigInt.fromI32(event.params.status); 95 | competition.save(); 96 | 97 | // Competition has opened, trigger PairCreated to follow `Swap` events. 98 | if (BigInt.fromI32(event.params.status).equals(BI_ONE)) { 99 | PairTemplate.create(Address.fromString(WBNB_BUSD)); 100 | 101 | log.info("Created pair with address {}.", [WBNB_BUSD]); 102 | TRACKED_TOKEN_BUSD_PAIRS.forEach((address: string) => { 103 | PairTemplate.create(Address.fromString(address)); 104 | 105 | log.info("Created pair with address {}.", [address]); 106 | }); 107 | TRACKED_TOKEN_BNB_PAIRS.forEach((address: string) => { 108 | PairTemplate.create(Address.fromString(address)); 109 | 110 | log.info("Created pair with address {}.", [address]); 111 | }); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v3/mappings/pair.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigDecimal, log } from "@graphprotocol/graph-ts"; 3 | import { Bundle, Competition, Team, User, PairStats } from "../generated/schema"; 4 | import { Swap } from "../generated/templates/Pair/Pair"; 5 | import { 6 | BD_1E18, 7 | BD_ZERO, 8 | BI_ONE, 9 | MOBOX_BNB, 10 | MOBOX_BUSD, 11 | TRACKED_TOKEN_BNB_PAIRS, 12 | TRACKED_TOKEN_BUSD_PAIRS, 13 | } from "./utils"; 14 | 15 | /** 16 | * SWAP 17 | */ 18 | 19 | export function handleSwap(event: Swap): void { 20 | let competition = Competition.load("3"); 21 | // Competition is not in progress, ignoring trade. 22 | if (competition.status.notEqual(BI_ONE)) { 23 | log.info("Competition is not in progress, ignoring trade; status: {}", [competition.status.toString()]); 24 | return; 25 | } 26 | 27 | // User is not registered for the competition, skipping. 28 | let user = User.load(event.transaction.from.toHex()); 29 | if (user === null) { 30 | log.info("User is not registered, ignoring trade; user: {}", [event.transaction.from.toHex()]); 31 | return; 32 | } 33 | 34 | // We load other entities as the trade is doomed valid and competition is in progress. 35 | let bundle = Bundle.load("1"); 36 | let team = Team.load(user.team); 37 | 38 | let bnbIN: BigDecimal; 39 | let bnbOUT: BigDecimal; 40 | 41 | let busdIN: BigDecimal; 42 | let busdOUT: BigDecimal; 43 | 44 | log.info("Pair info: {}, amount0In: {}, amount1In: {}, amount0Out: {}, amount1Out: {}", [ 45 | event.address.toHex(), 46 | event.params.amount0In.toString(), 47 | event.params.amount1In.toString(), 48 | event.params.amount0Out.toString(), 49 | event.params.amount1Out.toString(), 50 | ]); 51 | 52 | if (TRACKED_TOKEN_BUSD_PAIRS.includes(event.address.toHex())) { 53 | busdIN = event.params.amount1In.toBigDecimal().div(BD_1E18); 54 | busdOUT = event.params.amount1Out.toBigDecimal().div(BD_1E18); 55 | log.info("Pair found: {}, busdIN: {}, busdOUT: {}", [event.address.toHex(), busdIN.toString(), busdOUT.toString()]); 56 | } else if (TRACKED_TOKEN_BNB_PAIRS.includes(event.address.toHex())) { 57 | bnbIN = event.params.amount1In.toBigDecimal().div(BD_1E18); 58 | bnbOUT = event.params.amount1Out.toBigDecimal().div(BD_1E18); 59 | log.info("Pair found: {}, bnbIN: {}, bnbOUT: {}", [event.address.toHex(), bnbIN.toString(), bnbOUT.toString()]); 60 | } else { 61 | log.info("Pair not tracked: {}", [event.address.toHex()]); 62 | return; 63 | } 64 | 65 | let volumeBNB: BigDecimal; 66 | let volumeUSD: BigDecimal; 67 | if (bnbIN) { 68 | volumeBNB = bnbOUT.plus(bnbIN); 69 | volumeUSD = volumeBNB.times(bundle.bnbPrice); 70 | } else { 71 | volumeUSD = busdIN.plus(busdOUT); 72 | volumeBNB = volumeUSD.div(bundle.bnbPrice); 73 | } 74 | 75 | log.info("Volume: {} for {} BNB, or {} USD", [ 76 | event.transaction.from.toHex(), 77 | volumeBNB.toString(), 78 | volumeUSD.toString(), 79 | ]); 80 | 81 | // Fail safe condition in case the pairStats has already been created. 82 | let pairStats = PairStats.load(event.address.toHex()); 83 | if (pairStats === null) { 84 | pairStats = new PairStats(event.address.toHex()); 85 | pairStats.volumeUSD = BD_ZERO; 86 | pairStats.volumeBNB = BD_ZERO; 87 | pairStats.save(); 88 | } 89 | pairStats.volumeUSD = pairStats.volumeUSD.plus(volumeUSD); 90 | pairStats.volumeBNB = pairStats.volumeBNB.plus(volumeBNB); 91 | pairStats.save(); 92 | 93 | user.volumeUSD = user.volumeUSD.plus(volumeUSD); 94 | user.volumeBNB = user.volumeBNB.plus(volumeBNB); 95 | if (event.address.toHex() == MOBOX_BNB || event.address.toHex() == MOBOX_BUSD) { 96 | user.moboxVolumeUSD = user.moboxVolumeUSD.plus(volumeUSD); 97 | user.moboxVolumeBNB = user.moboxVolumeBNB.plus(volumeBNB); 98 | } 99 | user.txCount = user.txCount.plus(BI_ONE); 100 | user.save(); 101 | 102 | // Team statistics. 103 | team.volumeUSD = team.volumeUSD.plus(volumeUSD); 104 | team.volumeBNB = team.volumeBNB.plus(volumeBNB); 105 | team.txCount = team.txCount.plus(BI_ONE); 106 | team.save(); 107 | 108 | // Competition statistics. 109 | competition.volumeUSD = competition.volumeUSD.plus(volumeUSD); 110 | competition.volumeBNB = competition.volumeBNB.plus(volumeBNB); 111 | competition.txCount = competition.txCount.plus(BI_ONE); 112 | competition.save(); 113 | } 114 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v3/mappings/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts"; 3 | import { Pair } from "../../generated/templates/Pair/Pair"; 4 | 5 | export let BI_ZERO = BigInt.fromI32(0); 6 | export let BI_ONE = BigInt.fromI32(1); 7 | export let BD_ZERO = BigDecimal.fromString("0"); 8 | export let BD_1E18 = BigDecimal.fromString("1e18"); 9 | 10 | export const WBNB_BUSD = "0x58F876857a02D6762E0101bb5C46A8c1ED44Dc16"; 11 | 12 | export const MOBOX_BNB = "0x8fa59693458289914db0097f5f366d771b7a7c3f"; 13 | export const MOBOX_BUSD = "0x9a4e0660e658e7b4a284079c6c10a5ba74e13926"; 14 | 15 | export let TRACKED_TOKEN_BNB_PAIRS: string[] = [ 16 | MOBOX_BNB, 17 | "0x0ed7e52944161450477ee417de9cd3a859b14fd0", // CAKE/BNB 18 | ]; 19 | 20 | export let TRACKED_TOKEN_BUSD_PAIRS: string[] = [ 21 | MOBOX_BUSD, 22 | "0x804678fa97d91b974ec2af3c843270886528a9e6", // CAKE/BUSD 23 | ]; 24 | 25 | export function getBnbPriceInUSD(): BigDecimal { 26 | // Bind WBNB/BUSD contract to query the pair. 27 | let pairContract = Pair.bind(Address.fromString(WBNB_BUSD)); 28 | 29 | // Fail-safe call to get BNB price as BUSD. 30 | let reserves = pairContract.try_getReserves(); 31 | if (!reserves.reverted) { 32 | let reserve0 = reserves.value.value0.toBigDecimal().div(BD_1E18); 33 | let reserve1 = reserves.value.value1.toBigDecimal().div(BD_1E18); 34 | 35 | if (reserve0.notEqual(BD_ZERO)) { 36 | return reserve1.div(reserve0); 37 | } 38 | } 39 | 40 | return BD_ZERO; 41 | } 42 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trading-competition-v3", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/trading-competition-v3 subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v3/schema.graphql: -------------------------------------------------------------------------------- 1 | type Bundle @entity { 2 | id: ID! 3 | 4 | # Price in USD for BNB, derived from WBNB/BUSD pair 5 | bnbPrice: BigDecimal! 6 | 7 | # Block number 8 | block: BigInt! 9 | } 10 | 11 | type Competition @entity { 12 | id: ID! 13 | 14 | # Status 15 | status: BigInt! 16 | 17 | # Users 18 | userCount: BigInt! 19 | users: [User!]! @derivedFrom(field: "competition") 20 | 21 | # Volume 22 | volumeUSD: BigDecimal! 23 | volumeBNB: BigDecimal! 24 | 25 | # Transactions count 26 | txCount: BigInt! 27 | } 28 | 29 | type Team @entity { 30 | id: ID! # address 31 | 32 | # Users 33 | userCount: BigInt! 34 | users: [User!]! @derivedFrom(field: "team") 35 | 36 | # Volume 37 | volumeUSD: BigDecimal! 38 | volumeBNB: BigDecimal! 39 | 40 | # Transactions count 41 | txCount: BigInt! 42 | } 43 | 44 | type User @entity { 45 | id: ID! # address 46 | 47 | # Competition 48 | competition: Competition! 49 | 50 | # Team 51 | team: Team! 52 | 53 | # Block number 54 | block: BigInt! 55 | 56 | # Total Volume 57 | volumeUSD: BigDecimal! 58 | volumeBNB: BigDecimal! 59 | 60 | # Mobox Volume 61 | moboxVolumeUSD: BigDecimal! 62 | moboxVolumeBNB: BigDecimal! 63 | 64 | # Transactions count 65 | txCount: BigInt! 66 | } 67 | 68 | type PairStats @entity { 69 | id: ID! # address 70 | 71 | # Volume 72 | volumeUSD: BigDecimal! 73 | volumeBNB: BigDecimal! 74 | } -------------------------------------------------------------------------------- /subgraphs/trading-competition/v3/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Pancake Trading Competition V3 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: TradingCompetitionV3 9 | network: bsc 10 | source: 11 | address: '0x1C5161CdB145dE35a8961F82b065fd1F75C3BaDf' 12 | abi: TradingCompetitionV3 13 | startBlock: 16557618 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/competition.ts 19 | entities: 20 | - Bundle 21 | - Competition 22 | - Team 23 | - User 24 | - PairStats 25 | abis: 26 | - name: TradingCompetitionV3 27 | file: ./abis/TradingCompetitionV3.json 28 | - name: Factory 29 | file: ./abis/Factory.json 30 | - name: Pair 31 | file: ./abis/Pair.json 32 | blockHandlers: 33 | - handler: handleBlock 34 | eventHandlers: 35 | - event: UserRegister(address,uint256,uint256) 36 | handler: handleUserRegister 37 | - event: NewCompetitionStatus(uint8,uint256) 38 | handler: handleNewCompetitionStatus 39 | templates: 40 | - kind: ethereum/contract 41 | name: Pair 42 | network: bsc 43 | source: 44 | abi: Pair 45 | mapping: 46 | kind: ethereum/events 47 | apiVersion: 0.0.4 48 | language: wasm/assemblyscript 49 | file: ./mappings/pair.ts 50 | entities: 51 | - Bundle 52 | - Competition 53 | - Team 54 | - User 55 | - PairStats 56 | abis: 57 | - name: Factory 58 | file: ./abis/Factory.json 59 | - name: Pair 60 | file: ./abis/Pair.json 61 | eventHandlers: 62 | - event: Swap(indexed address,uint256,uint256,uint256,uint256,indexed address) 63 | handler: handleSwap 64 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v4/abis/Factory.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_feeToSetter", 7 | "type": "address" 8 | } 9 | ], 10 | "payable": false, 11 | "stateMutability": "nonpayable", 12 | "type": "constructor" 13 | }, 14 | { 15 | "anonymous": false, 16 | "inputs": [ 17 | { 18 | "indexed": true, 19 | "internalType": "address", 20 | "name": "token0", 21 | "type": "address" 22 | }, 23 | { 24 | "indexed": true, 25 | "internalType": "address", 26 | "name": "token1", 27 | "type": "address" 28 | }, 29 | { 30 | "indexed": false, 31 | "internalType": "address", 32 | "name": "pair", 33 | "type": "address" 34 | }, 35 | { 36 | "indexed": false, 37 | "internalType": "uint256", 38 | "name": "", 39 | "type": "uint256" 40 | } 41 | ], 42 | "name": "PairCreated", 43 | "type": "event" 44 | }, 45 | { 46 | "constant": true, 47 | "inputs": [], 48 | "name": "INIT_CODE_PAIR_HASH", 49 | "outputs": [ 50 | { 51 | "internalType": "bytes32", 52 | "name": "", 53 | "type": "bytes32" 54 | } 55 | ], 56 | "payable": false, 57 | "stateMutability": "view", 58 | "type": "function" 59 | }, 60 | { 61 | "constant": true, 62 | "inputs": [ 63 | { 64 | "internalType": "uint256", 65 | "name": "", 66 | "type": "uint256" 67 | } 68 | ], 69 | "name": "allPairs", 70 | "outputs": [ 71 | { 72 | "internalType": "address", 73 | "name": "", 74 | "type": "address" 75 | } 76 | ], 77 | "payable": false, 78 | "stateMutability": "view", 79 | "type": "function" 80 | }, 81 | { 82 | "constant": true, 83 | "inputs": [], 84 | "name": "allPairsLength", 85 | "outputs": [ 86 | { 87 | "internalType": "uint256", 88 | "name": "", 89 | "type": "uint256" 90 | } 91 | ], 92 | "payable": false, 93 | "stateMutability": "view", 94 | "type": "function" 95 | }, 96 | { 97 | "constant": false, 98 | "inputs": [ 99 | { 100 | "internalType": "address", 101 | "name": "tokenA", 102 | "type": "address" 103 | }, 104 | { 105 | "internalType": "address", 106 | "name": "tokenB", 107 | "type": "address" 108 | } 109 | ], 110 | "name": "createPair", 111 | "outputs": [ 112 | { 113 | "internalType": "address", 114 | "name": "pair", 115 | "type": "address" 116 | } 117 | ], 118 | "payable": false, 119 | "stateMutability": "nonpayable", 120 | "type": "function" 121 | }, 122 | { 123 | "constant": true, 124 | "inputs": [], 125 | "name": "feeTo", 126 | "outputs": [ 127 | { 128 | "internalType": "address", 129 | "name": "", 130 | "type": "address" 131 | } 132 | ], 133 | "payable": false, 134 | "stateMutability": "view", 135 | "type": "function" 136 | }, 137 | { 138 | "constant": true, 139 | "inputs": [], 140 | "name": "feeToSetter", 141 | "outputs": [ 142 | { 143 | "internalType": "address", 144 | "name": "", 145 | "type": "address" 146 | } 147 | ], 148 | "payable": false, 149 | "stateMutability": "view", 150 | "type": "function" 151 | }, 152 | { 153 | "constant": true, 154 | "inputs": [ 155 | { 156 | "internalType": "address", 157 | "name": "", 158 | "type": "address" 159 | }, 160 | { 161 | "internalType": "address", 162 | "name": "", 163 | "type": "address" 164 | } 165 | ], 166 | "name": "getPair", 167 | "outputs": [ 168 | { 169 | "internalType": "address", 170 | "name": "", 171 | "type": "address" 172 | } 173 | ], 174 | "payable": false, 175 | "stateMutability": "view", 176 | "type": "function" 177 | }, 178 | { 179 | "constant": false, 180 | "inputs": [ 181 | { 182 | "internalType": "address", 183 | "name": "_feeTo", 184 | "type": "address" 185 | } 186 | ], 187 | "name": "setFeeTo", 188 | "outputs": [], 189 | "payable": false, 190 | "stateMutability": "nonpayable", 191 | "type": "function" 192 | }, 193 | { 194 | "constant": false, 195 | "inputs": [ 196 | { 197 | "internalType": "address", 198 | "name": "_feeToSetter", 199 | "type": "address" 200 | } 201 | ], 202 | "name": "setFeeToSetter", 203 | "outputs": [], 204 | "payable": false, 205 | "stateMutability": "nonpayable", 206 | "type": "function" 207 | } 208 | ] 209 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v4/mappings/competition.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigInt, ethereum, log } from "@graphprotocol/graph-ts"; 3 | import { Bundle, Competition, Team, User } from "../generated/schema"; 4 | import { Pair as PairTemplate } from "../generated/templates"; 5 | import { NewCompetitionStatus, UserRegister } from "../generated/TradingCompetitionV4/TradingCompetitionV4"; 6 | import { 7 | BD_ZERO, 8 | BI_ONE, 9 | BI_ZERO, 10 | getBnbPriceInUSD, 11 | TRACKED_TOKEN_BUSD_PAIRS, 12 | TRACKED_TOKEN_BNB_PAIRS, 13 | WBNB_BUSD, 14 | } from "./utils"; 15 | 16 | /** 17 | * BLOCK 18 | */ 19 | 20 | export function handleBlock(event: ethereum.Block): void { 21 | // Fail safe condition in case the bundle has already been created. 22 | let bundle = Bundle.load("1"); 23 | if (bundle === null) { 24 | bundle = new Bundle("1"); 25 | bundle.bnbPrice = BD_ZERO; 26 | bundle.block = BI_ZERO; 27 | bundle.save(); 28 | } 29 | bundle.bnbPrice = getBnbPriceInUSD(); 30 | bundle.block = event.number; 31 | bundle.save(); 32 | } 33 | 34 | /** 35 | * COMPETITION 36 | */ 37 | 38 | export function handleUserRegister(event: UserRegister): void { 39 | // Fail safe condition in case the competition has already been created. 40 | let competition = Competition.load(event.params.competitionId.toString()); 41 | if (competition === null) { 42 | competition = new Competition(event.params.competitionId.toString()); 43 | competition.status = BI_ZERO; // Registration 44 | competition.userCount = BI_ZERO; 45 | competition.volumeUSD = BD_ZERO; 46 | competition.volumeBNB = BD_ZERO; 47 | competition.txCount = BI_ZERO; 48 | competition.save(); 49 | } 50 | competition.userCount = competition.userCount.plus(BI_ONE); 51 | competition.save(); 52 | 53 | // Fail safe condition in case the team has already been created. 54 | let team = Team.load(event.params.teamId.toString()); // Use `String` instead of `hex` to make the reconciliation simpler. 55 | if (team === null) { 56 | team = new Team(event.params.teamId.toString()); 57 | team.userCount = BI_ZERO; 58 | team.volumeUSD = BD_ZERO; 59 | team.volumeBNB = BD_ZERO; 60 | team.txCount = BI_ZERO; 61 | team.save(); 62 | } 63 | team.userCount = team.userCount.plus(BI_ONE); 64 | team.save(); 65 | 66 | // Fail safe condition in case the user has already been created. 67 | let user = User.load(event.params.userAddress.toHex()); 68 | if (user === null) { 69 | user = new User(event.params.userAddress.toHex()); 70 | user.competition = competition.id; 71 | user.team = team.id; 72 | user.block = event.block.number; 73 | user.volumeUSD = BD_ZERO; 74 | user.volumeBNB = BD_ZERO; 75 | user.darVolumeUSD = BD_ZERO; 76 | user.darVolumeBNB = BD_ZERO; 77 | user.txCount = BI_ZERO; 78 | user.save(); 79 | } 80 | } 81 | 82 | export function handleNewCompetitionStatus(event: NewCompetitionStatus): void { 83 | // Fail safe condition in case the competition has already been created. 84 | let competition = Competition.load(event.params.competitionId.toString()); 85 | if (competition === null) { 86 | competition = new Competition(event.params.competitionId.toString()); 87 | competition.status = BI_ZERO; // Registration 88 | competition.userCount = BI_ZERO; 89 | competition.volumeUSD = BD_ZERO; 90 | competition.volumeBNB = BD_ZERO; 91 | competition.txCount = BI_ZERO; 92 | competition.save(); 93 | } 94 | competition.status = BigInt.fromI32(event.params.status); 95 | competition.save(); 96 | 97 | // Competition has opened, trigger PairCreated to follow `Swap` events. 98 | if (BigInt.fromI32(event.params.status).equals(BI_ONE)) { 99 | PairTemplate.create(Address.fromString(WBNB_BUSD)); 100 | 101 | log.info("Created pair with address {}.", [WBNB_BUSD]); 102 | TRACKED_TOKEN_BUSD_PAIRS.forEach((address: string) => { 103 | PairTemplate.create(Address.fromString(address)); 104 | 105 | log.info("Created pair with address {}.", [address]); 106 | }); 107 | TRACKED_TOKEN_BNB_PAIRS.forEach((address: string) => { 108 | PairTemplate.create(Address.fromString(address)); 109 | 110 | log.info("Created pair with address {}.", [address]); 111 | }); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v4/mappings/pair.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { BigDecimal, log } from "@graphprotocol/graph-ts"; 3 | import { Bundle, Competition, Team, User, PairStats } from "../generated/schema"; 4 | import { Swap } from "../generated/templates/Pair/Pair"; 5 | import { BD_1E18, BD_ZERO, BI_ONE, DAR_BNB, TRACKED_TOKEN_BNB_PAIRS, TRACKED_TOKEN_BUSD_PAIRS } from "./utils"; 6 | 7 | /** 8 | * SWAP 9 | */ 10 | 11 | export function handleSwap(event: Swap): void { 12 | let competition = Competition.load("4"); 13 | // Competition is not in progress, ignoring trade. 14 | if (competition.status.notEqual(BI_ONE)) { 15 | log.info("Competition is not in progress, ignoring trade; status: {}", [competition.status.toString()]); 16 | return; 17 | } 18 | 19 | // User is not registered for the competition, skipping. 20 | let user = User.load(event.transaction.from.toHex()); 21 | if (user === null) { 22 | log.info("User is not registered, ignoring trade; user: {}", [event.transaction.from.toHex()]); 23 | return; 24 | } 25 | 26 | // We load other entities as the trade is doomed valid and competition is in progress. 27 | let bundle = Bundle.load("1"); 28 | let team = Team.load(user.team); 29 | 30 | let bnbIN: BigDecimal; 31 | let bnbOUT: BigDecimal; 32 | 33 | let busdIN: BigDecimal; 34 | let busdOUT: BigDecimal; 35 | 36 | log.info("Pair info: {}, amount0In: {}, amount1In: {}, amount0Out: {}, amount1Out: {}", [ 37 | event.address.toHex(), 38 | event.params.amount0In.toString(), 39 | event.params.amount1In.toString(), 40 | event.params.amount0Out.toString(), 41 | event.params.amount1Out.toString(), 42 | ]); 43 | 44 | if (TRACKED_TOKEN_BUSD_PAIRS.includes(event.address.toHex())) { 45 | busdIN = event.params.amount1In.toBigDecimal().div(BD_1E18); 46 | busdOUT = event.params.amount1Out.toBigDecimal().div(BD_1E18); 47 | log.info("Pair found: {}, busdIN: {}, busdOUT: {}", [event.address.toHex(), busdIN.toString(), busdOUT.toString()]); 48 | } else if (TRACKED_TOKEN_BNB_PAIRS.includes(event.address.toHex())) { 49 | bnbIN = event.params.amount1In.toBigDecimal().div(BD_1E18); 50 | bnbOUT = event.params.amount1Out.toBigDecimal().div(BD_1E18); 51 | log.info("Pair found: {}, bnbIN: {}, bnbOUT: {}", [event.address.toHex(), bnbIN.toString(), bnbOUT.toString()]); 52 | } else { 53 | log.info("Pair not tracked: {}", [event.address.toHex()]); 54 | return; 55 | } 56 | 57 | let volumeBNB: BigDecimal; 58 | let volumeUSD: BigDecimal; 59 | if (bnbIN) { 60 | volumeBNB = bnbOUT.plus(bnbIN); 61 | volumeUSD = volumeBNB.times(bundle.bnbPrice); 62 | } else { 63 | volumeUSD = busdIN.plus(busdOUT); 64 | volumeBNB = volumeUSD.div(bundle.bnbPrice); 65 | } 66 | 67 | log.info("Volume: {} for {} BNB, or {} USD", [ 68 | event.transaction.from.toHex(), 69 | volumeBNB.toString(), 70 | volumeUSD.toString(), 71 | ]); 72 | 73 | // Fail safe condition in case the pairStats has already been created. 74 | let pairStats = PairStats.load(event.address.toHex()); 75 | if (pairStats === null) { 76 | pairStats = new PairStats(event.address.toHex()); 77 | pairStats.volumeUSD = BD_ZERO; 78 | pairStats.volumeBNB = BD_ZERO; 79 | pairStats.save(); 80 | } 81 | pairStats.volumeUSD = pairStats.volumeUSD.plus(volumeUSD); 82 | pairStats.volumeBNB = pairStats.volumeBNB.plus(volumeBNB); 83 | pairStats.save(); 84 | 85 | user.volumeUSD = user.volumeUSD.plus(volumeUSD); 86 | user.volumeBNB = user.volumeBNB.plus(volumeBNB); 87 | if (event.address.toHex() == DAR_BNB) { 88 | user.darVolumeUSD = user.darVolumeUSD.plus(volumeUSD); 89 | user.darVolumeBNB = user.darVolumeBNB.plus(volumeBNB); 90 | } 91 | user.txCount = user.txCount.plus(BI_ONE); 92 | user.save(); 93 | 94 | // Team statistics. 95 | team.volumeUSD = team.volumeUSD.plus(volumeUSD); 96 | team.volumeBNB = team.volumeBNB.plus(volumeBNB); 97 | team.txCount = team.txCount.plus(BI_ONE); 98 | team.save(); 99 | 100 | // Competition statistics. 101 | competition.volumeUSD = competition.volumeUSD.plus(volumeUSD); 102 | competition.volumeBNB = competition.volumeBNB.plus(volumeBNB); 103 | competition.txCount = competition.txCount.plus(BI_ONE); 104 | competition.save(); 105 | } 106 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v4/mappings/utils/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable prefer-const */ 2 | import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts"; 3 | import { Pair } from "../../generated/templates/Pair/Pair"; 4 | 5 | export let BI_ZERO = BigInt.fromI32(0); 6 | export let BI_ONE = BigInt.fromI32(1); 7 | export let BD_ZERO = BigDecimal.fromString("0"); 8 | export let BD_1E18 = BigDecimal.fromString("1e18"); 9 | 10 | export const WBNB_BUSD = "0x58F876857a02D6762E0101bb5C46A8c1ED44Dc16"; 11 | 12 | export const DAR_BNB = "0x062f88e2b4896e823ac78ac314468c29eec4186d"; 13 | 14 | export let TRACKED_TOKEN_BNB_PAIRS: string[] = [ 15 | DAR_BNB, 16 | "0x0ed7e52944161450477ee417de9cd3a859b14fd0", // CAKE/BNB 17 | ]; 18 | 19 | export let TRACKED_TOKEN_BUSD_PAIRS: string[] = [ 20 | "0x804678fa97d91b974ec2af3c843270886528a9e6", // CAKE/BUSD 21 | ]; 22 | 23 | export function getBnbPriceInUSD(): BigDecimal { 24 | // Bind WBNB/BUSD contract to query the pair. 25 | let pairContract = Pair.bind(Address.fromString(WBNB_BUSD)); 26 | 27 | // Fail-safe call to get BNB price as BUSD. 28 | let reserves = pairContract.try_getReserves(); 29 | if (!reserves.reverted) { 30 | let reserve0 = reserves.value.value0.toBigDecimal().div(BD_1E18); 31 | let reserve1 = reserves.value.value1.toBigDecimal().div(BD_1E18); 32 | 33 | if (reserve0.notEqual(BD_ZERO)) { 34 | return reserve1.div(reserve0); 35 | } 36 | } 37 | 38 | return BD_ZERO; 39 | } 40 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trading-competition-v4", 3 | "description": "PancakeSwap Subgraph", 4 | "version": "1.0.0", 5 | "repository": "git@github.com:pancakeswap/pancake-subgraph.git", 6 | "author": "PancakeSwap", 7 | "license": "GPL-3.0-or-later", 8 | "scripts": { 9 | "codegen": "graph codegen subgraph.yaml", 10 | "build": "graph build subgraph.yaml", 11 | "deploy": "graph deploy --product hosted-service --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ pancakeswap/trading-competition-v4 subgraph.yaml" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subgraphs/trading-competition/v4/schema.graphql: -------------------------------------------------------------------------------- 1 | type Bundle @entity { 2 | id: ID! 3 | 4 | # Price in USD for BNB, derived from WBNB/BUSD pair 5 | bnbPrice: BigDecimal! 6 | 7 | # Block number 8 | block: BigInt! 9 | } 10 | 11 | type Competition @entity { 12 | id: ID! 13 | 14 | # Status 15 | status: BigInt! 16 | 17 | # Users 18 | userCount: BigInt! 19 | users: [User!]! @derivedFrom(field: "competition") 20 | 21 | # Volume 22 | volumeUSD: BigDecimal! 23 | volumeBNB: BigDecimal! 24 | 25 | # Transactions count 26 | txCount: BigInt! 27 | } 28 | 29 | type Team @entity { 30 | id: ID! # address 31 | 32 | # Users 33 | userCount: BigInt! 34 | users: [User!]! @derivedFrom(field: "team") 35 | 36 | # Volume 37 | volumeUSD: BigDecimal! 38 | volumeBNB: BigDecimal! 39 | 40 | # Transactions count 41 | txCount: BigInt! 42 | } 43 | 44 | type User @entity { 45 | id: ID! # address 46 | 47 | # Competition 48 | competition: Competition! 49 | 50 | # Team 51 | team: Team! 52 | 53 | # Block number 54 | block: BigInt! 55 | 56 | # Total Volume 57 | volumeUSD: BigDecimal! 58 | volumeBNB: BigDecimal! 59 | 60 | # Dar Volume 61 | darVolumeUSD: BigDecimal! 62 | darVolumeBNB: BigDecimal! 63 | 64 | # Transactions count 65 | txCount: BigInt! 66 | } 67 | 68 | type PairStats @entity { 69 | id: ID! # address 70 | 71 | # Volume 72 | volumeUSD: BigDecimal! 73 | volumeBNB: BigDecimal! 74 | } -------------------------------------------------------------------------------- /subgraphs/trading-competition/v4/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.2 2 | description: Pancake Trading Competition V4 3 | repository: https://github.com/pancakeswap 4 | schema: 5 | file: ./schema.graphql 6 | dataSources: 7 | - kind: ethereum/contract 8 | name: TradingCompetitionV4 9 | network: bsc 10 | source: 11 | address: '0x9F9b4728Cff3eb28aA8dC21482D3b542e4c6d039' 12 | abi: TradingCompetitionV4 13 | startBlock: 17594010 14 | mapping: 15 | kind: ethereum/events 16 | apiVersion: 0.0.4 17 | language: wasm/assemblyscript 18 | file: ./mappings/competition.ts 19 | entities: 20 | - Bundle 21 | - Competition 22 | - Team 23 | - User 24 | - PairStats 25 | abis: 26 | - name: TradingCompetitionV4 27 | file: ./abis/TradingCompetitionV4.json 28 | - name: Factory 29 | file: ./abis/Factory.json 30 | - name: Pair 31 | file: ./abis/Pair.json 32 | blockHandlers: 33 | - handler: handleBlock 34 | eventHandlers: 35 | - event: UserRegister(address,uint256,uint256) 36 | handler: handleUserRegister 37 | - event: NewCompetitionStatus(uint8,uint256) 38 | handler: handleNewCompetitionStatus 39 | templates: 40 | - kind: ethereum/contract 41 | name: Pair 42 | network: bsc 43 | source: 44 | abi: Pair 45 | mapping: 46 | kind: ethereum/events 47 | apiVersion: 0.0.4 48 | language: wasm/assemblyscript 49 | file: ./mappings/pair.ts 50 | entities: 51 | - Bundle 52 | - Competition 53 | - Team 54 | - User 55 | - PairStats 56 | abis: 57 | - name: Factory 58 | file: ./abis/Factory.json 59 | - name: Pair 60 | file: ./abis/Pair.json 61 | eventHandlers: 62 | - event: Swap(indexed address,uint256,uint256,uint256,uint256,indexed address) 63 | handler: handleSwap 64 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/@graphprotocol/graph-ts/tsconfig.json", 3 | "compilerOptions": { 4 | "types": ["@graphprotocol/graph-ts"] 5 | } 6 | } --------------------------------------------------------------------------------