# Galxe Astronaut Program
Source: https://docs.galxe.com/about/community-programs/galxe-astronaut
Dive in to learn how you can accrue points and progress through the tiers to unlock an array of exciting rewards in Galxe Astronaut Program.
Introducing the Galxe Astronaut Program — an exciting and interactive approach to celebrating your participation in the [Galxe Discord community](https://discord.com/invite/galxe). This system will ensure your efforts receive the recognition and rewards they deserve!
The Astronaut Program comprises three distinct tiers: Bronze, Silver, and Gold, each offering a bespoke array of rewards to elevate every phase of your adventure. Dive in to learn how you can accrue points and progress through the tiers to unlock an array of exciting rewards.
**System Mechanics**
The Astronaut Ranking System celebrates your milestones and input at every juncture of your voyage. Here’s an overview of the tiers:
* **Gold Tier**: Allocated for the elite 5% of our explorers, symbolizing the pinnacle of excellence within our cosmos.
* **Silver Tier**: Encapsulates 45% of our explorers, forming the core of our universe.
* **Bronze Tier**: Represents the foundational 50% of our explorers, integral to our expansive family.
**Point Allocation**
Your ranking is a composite of your engagements on the Galxe platform and contributions to our community, balanced to ensure equity. This encompasses participation in Galxe events, utilization of paid features, loyalty points, Web3 Score, and Galxe OG NFTs. Below is a breakdown of the factors influencing your ranking:
* Participation in Galxe Space Campaigns - 30%
* Utilization of Galxe Features (Smart Balance, Passport, Web3 Score) - 25%
* Loyalty Points - 25%
* Web3 Score - 20%
* Participation in OG Campaigns - 5%
Rest assured, your previous contributions, including earlier Galxe event participation and engagements, will be considered and evaluated using your wallet address.
**Tier Perks**
As you ascend through the tiers, you'll unlock increasingly substantial rewards and perks, enhancing your experience within the Galxe ecosystem.
**Advancement Insights**
Keen on advancing? Here are some strategies:
1. Engage actively in the Galxe Radio Show, participate in Snapshot votes, and immerse yourself in various Galxe events.
2. Embrace Galxe offerings such as the Galxe Passport, Galxe Web3 Score, and Galxe Smart Balance.
3. Elevate your Web3 Score by engaging with the Galxe ecosystem, particularly through Smart Balance utilization.
**Ascertain Your Cosmic Explorer Rank!**
Explore the Bronze, Silver, and Gold campaigns to identify your eligible Cosmic Explorer Rank.
# Galxe Contributor Program
Source: https://docs.galxe.com/about/community-programs/galxe-contributor
Galxe contributors are the backbone of the Galxe community and play a vital role in shaping the future of Web3.
After a lot of behind-the-scenes work, we’re excited to launch the brand new Galxe Contributor Program, which will revamp our current Brains & Pathfinders community programs. You will learn all about what the program entails in this blog, from multiple factions to a plethora of contributions you can participate in to become a real Galxe leader.
## What is a Galxe Contributor?
Galxe contributors are the backbone of the Galxe community and play a vital role in shaping the future of Web3. They are dedicated individuals who are committed to making a positive impact on the Galxe ecosystem, constantly looking for ways to improve the platform, and always eager to share their knowledge and expertise with others. Whether it's by contributing to the development of new features, shaping community events and programs, or helping to spread the word around, these individuals are true ambassadors for Galxe.
Galxe contributors are not only passionate about technology and the Web3 space, but they also have a strong desire to be a part of a community that shares the same vision. They understand the importance of community building and actively participate in community discussions, events and forums. They believe in the power of collaboration and strive to bring people together to achieve the common goal - helping Galxe grow!
## Why should you become a Galxe Contributor?
Becoming a Galxe contributor is a great opportunity to take a leadership role in shaping the future of the Galxe platform and the Web3 ecosystem. As a Galxe contributor, you will have the opportunity to work closely with the Galxe team, which will give you unique insights into the inner workings of the platform and allow you to help shape its direction.
* Work closely with the Galxe team
* Give feedback & suggestions to help shape the platform
* Lead the initiative in Galxe community events & programs
* Have a chance to participate in events hosted by Galxe
* Receive various rewards and exclusive Galxe swag
In summary, becoming a Galxe contributor is a unique opportunity to level up your Web3 journey, step up as a leader, shape the future of the platform, and be a part of a passionate and dedicated community that is committed to the growth and development of Galxe and the Web3 ecosystem.
## What are the Galxe Contributor Factions?
There are a variety of ways for someone to contribute to the Galxe ecosystem, and that is exactly why we believe this program will flourish even more if Galxe Contributors are given the freedom to choose what factions they would like to dedicate their time to.
The current Contributor Program factions are as follows:
* **Community & Content**: Create and share content via your own external social media accounts, including the latest updates about Galxe, newly launched features, and various campaigns. Lead the initiative for healthy community discussions, community campaigns, events, and Galxe Forum proposals.
* **Infrastructure & Support**: Help all the new and existing members of the community with various support requests, ensuring an easy, smooth and friendly Galxe journey.
* **Localization & Language-specific Community Leaders**: Lead the initiative to ensure our international and multilingual community is taken care of, including translations for official Galxe information, respective language community AMAs, language-specific community events & more.
With multiple factions, we open up opportunities for contributors to excel in multiple areas, rather than limiting their potential. For example, a Community & Content faction contributor can still contribute to other faction activities!
# G DAO
Source: https://docs.galxe.com/about/gal/dao
Understanding the governance of G DAO and how you can be part of it.
> Join the DAO discussions on [G DAO Forum](https://dao-forum.galxe.com)
> Check live snapshot proposals on [Snapshot](https://dao.galxe.com)
G DAO is managed by G stakers. G stakers have the ability manage funds held by the Galxe & Gravity Community Treasury. All proposals need to go through a three-step process described below. In order for a proposal to pass, it must have over 50% passing votes with endorsement from wallet addresses staking at least 120,000,000 G, with delegation allowed. When a proposal is passed, the changes will be implemented by Galxe’s operation team and signed by the multi-sig, if necessary.
All proposals need to go through the following process:
**Phase 1: Proposal Temperature Check - Forum**
The purpose of the Temperature Check is to determine if there is sufficient will to make changes to the status quo. To create a Temperature Check for your Proposal, follow the Proposal Template and post on the [DAO Governance category on G DAO Forum](https://dao-forum.galxe.com/c/governance/5).
**Proposal Template**:
* Abstract
* Motivation
* Specification
* Overview
* Scope
* Success Criteria
* Timeline/Budget
* References
The temperature check must be held for a period of at least 5 days. If feedback is sufficient, the proposal can move to Phase 2.
**Phase 2: Vote — Snapshot**
Once your proposal has passed the temperature check, you can work with the operation team to schedule a snapshot vote. [The snapshot vote](https://snapshot.org/#/gal.eth) will last for 5 days. In order for a proposal to pass, the GP must have:
* Over 50% passing votes
* Endorsement from wallet addresses staking at least 120,000,000 G
* If the proposal is asking for funds less than \$50,000 or does not implement significant change to the token/contract, the quorum for the vote is 12,000,000 G
When a proposal is passed, the changes will be implemented by Galxe’s operation team and signed by the multi-sig, if necessary.
The multi-signature wallet signers are selected and voted in by \$G stakers after token generation event. They are also subject to change from future governance votes.
# Tokenomics
Source: https://docs.galxe.com/about/gal/tokenomics
Understanding the GAL Token
Update on July 4, 2024: With the approval of proposals [GP-25](https://dao.galxe.com/#/proposal/0x8d3f386c3b0cb9fa170d4231c65f18bd45ea1402b90a70116e1101c22e62ed01) and [GP-30](https://dao.galxe.com/#/proposal/0xa6af134cd0522ea34d2d6485a557fafdb01cc7f32726f409bd8f399cc2af2514) by the Galxe DAO community, [Galxe (GAL)](https://coinmarketcap.com/currencies/galxe/) token will be upgraded to [Gravity (G)](https://coinmarketcap.com/currencies/gravity-token/), unifying and streamlining the experience across both ecosystems. This upgrade focuses on enhancing the user journey, integrating the token seamlessly across our Layer 1 and the Galxe ecosystem, and simplifying the ticker for easier recognition. G will serve as the universal token, providing utility in governance, transactions, and incentives across the entire ecosystem.
* Learn more about Gravity (G): [https://docs.gravity.xyz/tokens/g-token](https://docs.gravity.xyz/tokens/g-token)
* Official Portal for Upgrading GAL to G: [https://g.xyz/GAL-G-Portal](https://g.xyz/GAL-G-Portal)
* Learn more about the token migration: [https://gravity.xyz/blog/gal-g](https://gravity.xyz/blog/gal-g)
\-----------------------------------------
*The following information only applies to GAL*
\-----------------------------------------
### GAL Token Contracts
| Chain | Contract Address |
| --------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Ethereum ERC20 | [**0x5fAa989Af96Af85384b8a938c2EdE4A7378D9875**](https://etherscan.io/token/0x5faa989af96af85384b8a938c2ede4a7378d9875) |
| BNB Chain BEP20 | [**0xe4Cc45Bb5DBDA06dB6183E8bf016569f40497Aa5**](https://bscscan.com/token/0xe4Cc45Bb5DBDA06dB6183E8bf016569f40497Aa5) |
### Token Distribution
GAL has a total supply of 200,000,000 tokens.
Please visit [this token table](https://gal.org/token-table) for initial distribution, vesting detail and current circulating supply.
### Vesting Contracts
| Contract Address | Description |
| --------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| [0xdBa0F580521968895ccA2B1FdEd2c5CD6D075882](https://etherscan.io/address/0xdba0f580521968895cca2b1fded2c5cd6d075882) | **Growth Backer Round 1** |
| [0xC8F03241D10CA39A64492587AA443fb5ac660870](https://etherscan.io/address/0xC8F03241D10CA39A64492587AA443fb5ac660870) | **Growth Backer Round 2 & Advisory** |
| [0x0ca389eb320e4EC509dde88310b3C60953721a21](https://etherscan.io/address/0x0ca389eb320e4ec509dde88310b3c60953721a21) | **Marketing** |
| [0x0B318030c698fd4875726F2f08714a22B8C5f769](https://etherscan.io/address/0x0b318030c698fd4875726f2f08714a22b8c5f769) | **Foundation** |
| [0x65f2CA02E22e3635FDeC45b5360A4bB6832625C2](https://etherscan.io/address/0x65f2CA02E22e3635FDeC45b5360A4bB6832625C2) | **Team** |
| [0x8793C0b5EDB1Fea27B1aAc3F6FcbabD31B5A4ee7](https://etherscan.io/address/0x8793c0b5edb1fea27b1aac3f6fcbabd31b5a4ee7) | **Community Treasury** |
# Overview
Source: https://docs.galxe.com/about/introduction
Galxe is a decentralized super app and web3’s largest onchain distribution platform. Through its robust infrastructure and product suite of modular AI, digital identity, and blockchain technologies — Quest, Passport, Score, Compass, and Alva — Galxe supports the development of advanced, user-friendly web3 applications with an emphasis on secure and self-sovereign digital identity management.
# Galxe Ecosystem
## Galxe Identity Protocol
A revolutionary technology that utilizes privacy-preserving ZK technology to enable safe and seamless integration of digital identities across platforms. This protocol empowers both users and developers by allowing for the creation of revocable, onchain managed credentials, redefining how users engage and explore web3’s expanding universe of decentralized applications.
## Galxe Quest
The #1 platform for building and engaging with web3 communities, trusted by the most significant and reputable brands in the space. Through a turnkey, no-code solution, Quest connects projects and applications with millions of users through reward-based loyalty programs. Trusted by industry leaders like Optimism, Arbitrum, and Polygon, Galxe is your gateway web3’s largest onchain distribution platform with over 22 million users.
## Galxe Passport
A secure identity solution powered by Galxe Identity Protocol that simplifies online verification, enabling trusted, privacy-preserving web3 exploration.
## Galxe Score
Your web3 reputation score that mirrors your digital identity in the metaverse and other virtual environments, shaped by your onchain achievements, engagement, expertise, and assets, enabling new growth opportunities and access to exclusive benefits.
## Alva
An AI copilot that offers comprehensive support in project research, quantitative trading, and identifying lucrative opportunities across the web3 ecosystem. Instantly accessible through browser extension and GPTs, [Alva](https://alva.xyz) ensures access to crucial information, anytime and anywhere.
## Gravity
[Gravity](https://gravity.xyz) is a Layer 1 blockchain designed for mass adoption and an omnichain future. With over 90 million monthly transactions across 34+ supported chains, Gravity puts the user experience first. Its approach abstracts the technical complexities of multichain interactions, integrating advanced technologies like Zero-Knowledge Proofs, state-of-the-art consensus mechanisms, and restaking-powered architecture to ensure high performance, enhanced security, and cost efficiency.
Gravity serves the 22 million users in Galxe’s ecosystem, delivering a seamless and inviting experience to web3’s largest onchain distribution network.
# Galxe Passport Privacy Policy
Source: https://docs.galxe.com/about/legal/passport-privacy-policy
Last Updated: March 1, 2025
Summary of Our Privacy Policy
Welcome to GALXE Passport, Your universal identity for Web3 adventures! We are committed to protecting your privacy and this document describes in detail our data practices, including the types of data we collect and how we use this data. This summary is a short description of our Privacy Policy.
Our core Privacy Principles:
1. Anonymous and Secure
Your identity information will be encrypted with your password. This data is never stored in plain text and will not be accessible by anyone (including GALXE Passport) without your explicit permission.
2. Owning Access Control
You are in total control of your data. You can choose to share it with third parties or revoke it as you see fit.
3. Convenient
You only have to verify once to use your GALXE Passport across Web3 applications. You can use it for compliance processes or to simply prove yourself as a verified individual.
Information We Collect
We collect data require to verify your identity, which includes the following:
* Full name;
* Email address;
* Identity Verification Information, such as a picture of your Driver's License, State ID, or
* Passport;
* Picture of your face; and
* IP Address.
How We Use Your Information
The primary purpose for this data is to verify your identity. We work with a third party service provider, Sumsub, to verify your identity. You will upload your information, including identity verification Information, to Sumsub, who will then conduct the identity verification. Once your identity is verified, Sumsub will send to us a copy of the information you provided to verify your identity. We will pack the identity information into a verifiable credential, send it to you, and ask you to encrypt it with your password. After you send us the encrypted data, we will keep it safely stored on our servers, and delete all information we collected during the process. At this point, only you can use your password to decrypt and access your identity information. You may also decide that you want to share this information with another application. Instead of you taking pictures of your documents and uploading your information separately to a third party of your choosing, you can request the encrypted PII from GALXE, decrypt them locally with your password to get the PII in a verifiable credential format, and send it to the third party you trust.
Frequently Asked Questions
Q: How will my identity information be stored?
A: Your identity information will be encrypted with your password. GALXE Passport never stores identity information in plain text and will not have access to identity information.
Q: Who can access my identity information?
A: Because GALXE Passport does not store your password, only you can decrypt this data with your password. No one, including GALXE Passport, has access to your identity information without your permission.
Q: How can I use my GALXE Passport?
A: Partners (eg. IDO or INO platforms) who integrate GALXE ID SDK may ask for your identity information for compliance reasons. By granting them access to your GALXE Passport's identity information, you do not need to complete the verification process on their sites for additional times. Other partners may use GALXE Passport SBT as a proof-of-human mechanism to prevent sybil attack.
Q: If I participate in a campaign on GALXE which requires GALXE Passport credential, am I giving away my identity information?
A: No. GALXE Passport credential only looks at your GALXE Passport NFT holding in your wallet. GALXE Passport NFT is minted on BNB Chain with this contract address. Participating in these campaigns will not disclose your identity information.
Q: What happens if I lose my GALXE Passport password?
A: Because GALXE Passport does NOT store your password, there is no way to recover your password if you lose it. If you lose your password, you can still use your GALXE Passport as a proof-of-human NFT, however, you won't be able to decrypt your Sumsub data to share with other third parties for compliance purposes.
Q: What's Sumsub's role in the process?
A: Sumsub is the third party vendor that helps run algorithms and check whether your ID is valid. They collect the identity information directly from you because they need to provide the identity verification. Please note that your use of Sumsub's service is subject to Sumsub's Privacy Policy, which can be found here: [https://sumsub.com/privacy-notice-service/](https://sumsub.com/privacy-notice-service/) Sumsub then shares this information with GALXE Passport. However, they do not know which identity belongs to which address.
Q: Will I remain anonymous after I mint GALXE Passport?
A: Our third party identity verification vendor, Sumsub, only verifies your identity based on the documents and pictures you provide. Neither Sumsub, nor any other third party, has the capability to connect a user's verification documents to any particular wallet address. Therefore, verifying your information will not allow those third parties to tie any specific wallet address to any identifiable individual and you will remain anonymous. Likewise, minting a GALXE Passport token does not reveal your identity on the chain。
Q: Am I required to mint GALXE Passport in order to use GALXE?
A: No. None of the features on GALXE will require you to mint GALXE Passport. GALXE also does not require any of its partners to use GALXE Passport credential in their campaign. GALXE Passport credential is just like any other credential in the network. Campaign creators can choose to include or not include GALXE Passport credential as a requirement in their campaigns.
Q: What happens if any government agencies request users' information from GALXE Passport?
A: All user data is encrypted with your password. Therefore, we do not have access to and cannot view or share your information without your permission and password. Without your permission GALXE Passport does not have the password to decrypt the encrypted identity information.
PRIVACY POLICY
Last Updated: March 1, 2025
This Privacy Policy ("Policy") describes how Star Frameworks Labs Pte. Ltd., ("GALXE Passport” “we” “us” or “our”) collects, uses, and discloses information related to the users of the GALXE Passport, our website [https://galxe.com/passport](https://galxe.com/passport) ("Website”) and any other related and connected platforms and other online and offline interactions (collectively, the “Services”). Additional information on our Personal information practices may be provided at the time of data collection. Your use of our Services is subject to our Terms of Use, available at [https://galxe.com/passport](https://galxe.com/passport), which includes applicable terms governing limitations on liability and the resolution of disputes. By using the Services, you accept and agree to the practices described in this Policy. If you do not agree with this Policy, please do not use the Services or provide us with any Personal Information (as defined below).
Personal Information
For purposes of this Policy, unless otherwise required by applicable law, “Personal Information" means any information that (directly or indirectly) identifies, relates to, describes, or is reasonably capable of being associated, linked or linkable with a particular individual or household, including any information that is subject to applicable data protection laws.
Scope
This Policy applies to our collection, use and disclosure of Personal Information related to the users of our Services, and applies to all users of our Services.
Collection of Personal Information
The Personal Information we collect varies depending upon the nature of the Services provided or used and our interactions with individuals.
Categories of Personal Information. While the Personal Information we collect varies depending upon the circumstances and your interactions with the Service, we may collect the following categories of Personal Information (subject to applicable legal requirements and restrictions):
* Name, contact information and other identifiers: identifiers such as a name, username, account name, blockchain wallet address, mailing address, phone number, country of residence, birth date, email address, and online identifier.
* Customer records: electronic customer records containing Personal Information.
* Device information: internet protocol (IP) address, web browser type, operating system version, phone carrier and manufacturer, application installations, device identifiers, mobile advertising identifiers, and push notification tokens.
* Protected classifications, characteristics, or special category data: protected classifications or characteristics, or data considered "special category" under applicable law such as race,ethnicity, sex, age, and nationality.
* Identity documents: the document(s) you upload to our third party identity verification provider, such as driver's license, identification card, or passport, in addition to the information about those documents such as document type, document number, expiration date, and a picture or copy of those documents.
* Images and photographic data: photographic images received from or uploaded by you to a third party provider engaged by us to verify your identity.
* Communications: direct communication, web forms, online polls, or interactions with our blogs and posts. Usage data: internet or other electronic network activity information including, but not limited to, browsing history, search history, and information regarding a consumer's interaction with an Internet website, application, or advertisement.
* Location data: location information about a particular individual or device, general location information (for example, your IP address may indicate your more general geographic region).
Sources of Personal Information. We may collect Personal Information about individuals:
* Directly from you: such as when you create an online account with us (“User Account"), use the Service, participate in a transaction, communicate on the Services, participate in contests and promotions we offer, register to receive marketing and other communications from us, or contact us for customer support purposes.
* From our partners and service providers: when you use our services to verify your identity, we will work with our partner who is a third party service provider to collect your information and verify your identity; depending on your settings and the features you use, our partners may share that information with us.
* From third parties: such as affiliate and other third parties, public records, third-party providers of services to us (e.g., fraud detection and security), consumer data resellers, social networks, joint marketing partners and affiliate companies.
* Related to your use of our Services: including information we collect automatically when you use our Website or interact with us, or information we derive about you and your preferences or interests based on the Personal Information we collect and our interactions with you.
Information We Collect From You. We may collect Personal Information from you related to:
* Registration, accounts and profiles: if you choose to use our identity verification service, we collect and process information, including sensitive Personal information, necessary to comply with “Know Your Customer” or similar legal obligations under applicable laws in order to verify your identity. This includes your name, identity documents (such as driver's license or passport), and a picture of your face; we may also collect additional information such as your preferences and payment details.
* Your communications and requests: when you email us, call us, or otherwise send us communications, we collect and maintain a record of your contact details, communications and our responses.
Information We Collect from Third Parties. We may collect Personal Information about you from third-party sources (which may be combined with other Personal Information we have collected about you), such as:
* Identity Verification Service: We may collect information about you from third party entities when we seek to verify your identity as part of “Know Your Customer” requirements, including sensitive Personal information. We collect information from third party entities engaged by us to provide information about your identity, including identity documents (as described above), photographic data, and confirmation of your identity. Please note that use of this third-party service is optional but certain features of the Service may not be available to you unless you provide additional information.
* Third-party accounts: if you connect your third party accounts to your User Account (such as
Twitter, Discord, or GitHub), we will collect certain Personal information about you from those
third parties.
* Other: we may obtain Personal Information, such as demographic information or updated contact details, from third parties; we may also collect information from public records.
Information We Collect or Derive About You Automatically. We may collect or derive Personal Information about your use of our Services, or other interactions with us.
* Website and App: We and our third-party providers may use cookies, pixels, tags, log-files, and other technologies to collect information about a user from their browser or device, including, without limitation, your browser type, device type, operating system, software version, phone model, phone operating system, platform-dependent information, requested document, referring URL, date and time of your visit, clickstream data (e.g., about the pages you view, links you click and date and time stamps for your activities on our Website), and the IP address associated with your transactions in the system. The information that we collect automatically may be linked with other Personal Information we have collected.
Use of Personal Information
We will only process your Personal Information where we have legal grounds to do so. We may use Personal Information for a variety of purposes, including, without limitation:
* Providing support and services: including to provide our Services, operate our Website, and online services, and interact with you on our Services; to respond to your inquiries; to provide troubleshooting, fulfill your orders and requests, process your payments and provide technical support; and for other customer service and support purposes. Our lawful basis is to fulfill any contractual terms with you.
* Analyzing and improving our business: including to better understand how users access and use our Services, to evaluate and improve our Services and business operations, and to develop new features, offerings, and services; to conduct surveys and other evaluations (such as customer satisfaction surveys); to monitor consumer interest in our products and Services; to troubleshoot problems that may arise on the Services; to improve the accuracy of our customer database; to increase our understanding of our customers; and for other research and analytical purposes. Our lawful basis is our legitimate business interests in understanding and improving our Services.
* Personalizing content and experiences: including to tailor content we send or display on our Website and other Services and to otherwise Personalize your experiences. Our lawful basis is our legitimate business interests in offering a more Personalized service.
* Advertising and marketing and promotional purposes: including to reach you with more relevant ads and send you newsletters, offers or other information we think may interest you. However, we will not use any Identity Information (such as your passport information) for marketing or promotional purposes. We may use your name and email address to provide you with marketing or promotional communications, and you can always unsubscribe from marketing communications. Our lawful basis is your consent to choose to subscribe to any newsletter or marketing (and you can unsubscribe at any time).
* Securing and protecting our business: including to protect and secure our business operations, assets, Services, network and information and technology resources; to investigate, prevent, detect and take action regarding fraud, unauthorized access, situations involving potential threats to the rights or safety of any person or third-party, or other unauthorized activities or misconduct. Our lawful basis is our legitimate business interests in protecting our business and services.
* Defending our legal rights: including to manage and respond to actual and potential legal disputes and claims, and to otherwise establish, defend or protect our rights or interests, including in the context of anticipated or actual litigation with third parties. Our lawful basis is our legitimate business interests in protecting our business or our need to defend ourselves legally.
* Auditing, reporting, corporate governance, and internal operations: including relating to financial, tax and accounting audits; audits and assessments of our operations, privacy, security and financial controls, risk, and compliance with legal obligations; our general business, accounting, record keeping and legal functions; and related to any actual or contemplated merger, acquisition, asset sale or transfer, financing, bankruptcy or restructuring of all or part of our business. Our lawful basis is our legal obligations under relevant legislation such as tax reporting and our legitimate interests in running our governance programs.
* Complying with legal obligations: including to comply with the law, our legal obligations and legal process, such as warrants, subpoenas, court orders, and regulatory or law enforcement requests. Our lawful basis is compliance with applicable law.
* For our legitimate business interests: including our business interest in conducting and managing our business and enabling us to give you the best service/product and the best and most secure experience. We make sure we consider and balance any potential impact on you (both positive and negative) and your rights before we process your Personal Information for our legitimate interests. We do not use your Personal Information for activities where our interests are overridden by the impact on you (unless we have your consent or are otherwise required or permitted to by law). You can obtain further information about how we assess our legitimate interests against any potential impact on you in respect of specific activities by contacting us. Our lawful basis is this legitimate business interest.
Aggregate and De-identified Data. We may de-identify information and create anonymous and aggregated data sets and reports to assess, improve and develop our business, products and Services, prepare benchmarking reports on our industry and for other research, marketing and analytics purposes. De-identified information is not Personal Information and we may use de- identified information as allowed under applicable data protection laws.
We may combine information from different sources. For example, we may combine information that we have collected offline with information we collect online, or we may combine information we get from a third-party with information we already have. If you submit any Personal Information relating to other people to us, you represent that you have the authority to do so and have informed that other person about the contents of this Policy.
Disclosure of Personal Information
We may share or disclose the Personal Information we collect as follows:
* Service providers: We may disclose Personal Information to third-party service providers who use this information to perform services for us, such as third-party identity verification services, hosting providers, auditors, advisors, consultants, customer service and/or support providers.
* Third Party Platforms: At your request and only with your authorization, we will disclose your identity token and/or identity verification information you have provided to us, to third- party crypto exchanges, asset management platforms, web3 platforms and applications, defi platforms or other services where a KYC token may be required.
* Subsidiaries, affiliates, and business partners: We may share your Personal Information with our affiliated companies (i.e., our parent company and other companies under common ownership, control or management with us); they may use such Personal Information for the purposes set out in this Policy.
* Legal compliance: We may be required to share Personal Information in response to a valid court order, subpoena, government investigation, or as otherwise required by law. We also reserve the right to report to law enforcement agencies any activities that we, in good faith, believe to be unlawful. In addition, we may share certain Personal Information when we believe that doing so is reasonably necessary to protect the rights, property and safety of our company and/or others.
* Business transfers: We may disclose and/or transfer Personal Information as part of any actual or contemplated merger, sale, transfer of assets, acquisition, financing and/or restructuring of all or part of our business, bankruptcy or similar event, including related to due diligence conducted prior to such event where permitted by law.
* Protect our rights: We may disclose Personal Information where we believe it necessary to respond to claims asserted against us, to enforce or administer our agreements and terms, for fraud prevention, risk assessment, investigation and/or to protect the rights, property or safety of Galaxy or our affiliates, partners, clients, customers and/or others.
Aggregated and De-identified Data. We may share aggregate or de-identified information with third parties for research, marketing, advertising, analytics and/or other purposes.
What happens if you do not provide us with the Personal Information we request or ask that we stop processing your Personal Information?
If you do not provide the Personal Information we request, or if you withdraw your consent to the processing of your Personal Information, then you may be unable to use the Services.
Cookies and Analytics
We use cookies, pixels, tags, and other technologies, which may be provided by third parties, on our Services to enable certain functionality and for security and fraud detection and prevention, as well as to collect usage information about our Website and the emails that we send and to Personalize content and provide more relevant ads and information. We may combine the information we collect via these technologies with other information, including Personal Information.
Cookies. Cookies are alphanumeric identifiers that are transferred to your computer through your web browser for record-keeping purposes. Some cookies enable you to log-in to our Services or save certain settings and preferences, while others allow us to track usage and activities on our Services Personalize content, or deliver more relevant ads. Most web browsers automatically accept cookies, but if you prefer, you can edit your browser options to block them in the future. The "Help" tab on the toolbar on most browsers will tell you how to prevent your computer from accepting new cookies, how to have the browser notify you when you receive a new cookie, or how to disable cookies altogether. If you block cookies, however, certain features on our Website may not be available or function properly. Third parties may use cookies and other similar technologies to collect or receive information from our Site and elsewhere on the Internet and use that information to provide you with targeted ads. If you would like to opt-out of such advertising practices on the particular device on which you are accessing this Privacy Policy, please go to [http://optout.aboutads.info/](http://optout.aboutads.info/).
The Network Advertising Initiative also offers a means to opt-out of a number of advertising cookies. Please visit [http://www.networkadvertising.org](http://www.networkadvertising.org) to learn more. Note that opting-out does not mean you will no longer receive online advertising. It does mean that the company or companies from which you opted-out will no longer deliver ads tailored to your preferences and usage patterns.
Pixel tags and embedded script (aka clear GIFs and web beacons). Pixel tags are tiny graphics with a unique identifier, similar in function to cookies. In contrast to cookies, which are stored on your computer's hard drive, pixel tags are embedded invisibly on web pages. We may use these, in connection with our Website to, among other things, track the activities of the users of our Services, improve ads, personalize and manage content, and gather usage information about our Website. We may also use these in HTML emails to help us track email response rates, identify when our emails are viewed, and track whether our emails are forwarded.
Third-Party Analytics Tools. Our Website uses automated devices and applications operated by third parties, such as Google Analytics, which uses cookies and similar technologies to collect and analyze information about use of the Website and report on activities and trends. This service may also collect information regarding the use of other websites, apps and online resources. You can learn about Google's practices by going to [www.google.com/policies/privacy/partners/](http://www.google.com/policies/privacy/partners/), and you can opt out of them by downloading the Google Analytics opt-out browser add-on, available at [https://tools.google.com/dlpage/gaoptout](https://tools.google.com/dlpage/gaoptout).
Children's Privacy
Our Services are restricted for users at least 18 years old (or of legal age in their jurisdiction) and children under the age of 18 are not allowed to use our Services. Galaxy does not knowingly collect or maintain Personal Information from children we actually know at the time of collection are under the legal age. Should we discover that we have collected Personal Information online from a child who is under the legal age, we will promptly delete thatPersonal Information. Although our Services are not directed to children, if your child uses our Services and you wish to review or delete your child's Personal Information, you may so request by contacting us at the location or email address set forth below under 'Contact Us.'
Security
The security of your Personal Information is important to us. We have put in place safeguards to protect the Personal Information we collect from unauthorized access, use and disclosure, and we take steps to ensure that all of our employees, agents, contractors and other third parties have similar adequate measures in place. We also have procedures to deal with any suspected Personal Information breach, and we will notify you and any applicable regulator when we are legally required to do so. However, we cannot guarantee that unauthorized access, hacking, data loss, or other breaches will never occur. We urge you to take steps to keep your Sumsub Information safe, such as choosing a strong password and logging out of your User Account and closing your web browser when finished using the Services.
Opt-Out of Communications With Us
E-mail Contact. You may opt-out of receiving promotional e-mail communication from us by sending us an e-mail at [Support@galxe.com](mailto:Support@galxe.com), or by clicking the “unsubscribe" button at the bottom of our emails that we send to you. Please note that you will not be able to opt-out of transactional e-mail communication, such as communication related to your user account activities.
Push Notification. You can opt out of receiving push notifications through your device settings. Please note that opting out of receiving push notifications may impact your use of the Services.
Transfers outside the UK/Europe
For users in the UK and European Economic Area (“EEA”). We may sometimes transfer your Personal Information to countries outside the UK and EEA, for example if we are using a supplier based elsewhere or you want to transfer your data to a third-party based in another country. The privacy laws in countries outside the UK and EEA may be different from those in your home country. Where we transfer data to a country that has not been deemed to provide adequate data protection standards, we will always have security measures and approved European or UK model clauses (available on the European Union's legal website at eur-lex.europa.eu and the UK ones at the ICO website [www.ico.gov.uk](http://www.ico.gov.uk)) or other adequate safeguards in place to protect your Personal Information. Please contact us if you would like more details about our safeguards for data transfers outside of the UK/EEA.
For other users. If we transfer your Personal Information to countries outside of your home country, we will take steps to comply with the requirements for such transfer in your home country as required by relevant law.
Links to Third-party Websites
The Services provide links to various websites operated by third parties including, but not limited to, third-party sites that may display our trademarks. This Policy does not apply to third-party websites that are accessible through the Services, unless such website directs users or visitors to this Policy. When you click on one of these links, you will be transferred out of the Services and connected to the website of the organization or company that maintains that website. Even if an affiliation exists between us and a third-party website, we exercise no control over linked websites. Each of these linked websites maintains its own independent privacy and data collection policies and procedures. We encourage you to read the privacy policies of those other websites to learn how they collect, use, share, and secure your information before providing any Personal Information.
Retention
Except to the extent prohibited by law, and subject to this Policy, we will retain and use your Personal Information for as long as it is needed to provide you with any services, communications, information you have requested, or access to the Services, to document our business relationship with you, and as necessary to comply with our legal obligations, resolve disputes, and enforce our agreements. As soon as it is reasonable to assume your Personal Information is no longer needed or required, we will cease to retain your Personal Information, or remove the means by which the data can be associated with you. You should inform us of any changes to your Personal Information so that we can keep it up to date. If you wish to find out further information on how long we retain your Personal Information for you can contact us using the details below.
Your Data Access Rights
Depending on where you live, you may have a number of rights when it comes to your Personal Information. Further information and advice about your rights can be obtained from the data protection regulator in your country, and many countries provide a right to lodge a complaint with the regulator. The rights that may be available to you include rights such as:
European Union/EEA and United Kingdom
The right to be informed.
You have the right to be provided with clear, transparent and easily understandable information about how we use your Personal Information and your rights. This is why we are providing you with the information in this Policy. If you have any additional questions, for example regarding transfers and locations of data or our legitimate interests basis, please contact us.
The right of access.
You have the right to obtain access to your Personal Information (if we are processing it), and certain other information (similar to that provided in this Policy). This is so you are aware and can check that we're using your Personal Information in accordance with data protection law. The right to rectification.
This is also known as the ‘right to be forgotten' and enables you to request the deletion or removal of your information where there is no compelling reason for us to keep using it. This is not a general right, there are exceptions.
The right to restrict processing.
You have rights to 'block' or suppress further use of your Personal Information. When processing is restricted, we can still store your Personal Information, but we may not use it further. We keep lists of people who have asked for further use of their information to be ‘blocked' to make sure the restriction is respected in future.
The right to data portability.
You have the right to object to certain types of processing, including processing for direct marketing or where we are relying on our legitimate interests for processing.
The right to lodge a complaint.
You have the right to lodge a complaint about the way we handle or process your Personal Information with your national data protection regulator. In the UK, this is the Information Commissioner, and details of how to contact the ICO can be found on their website at ico.org.uk.
The right to withdraw consent.
If you have given your consent to anything we do with your Personal Information, you have the right to withdraw your consent at any time (although if you do so, it does not mean that anything we have done with your Personal data with your consent up to that point is unlawful). This includes your right to withdraw consent to us using your Personal data for marketing purposes. We usually act on requests and provide information free of charge, but we may charge a reasonable fee to cover our administrative costs of providing the information for baseless or excessive/repeated requests, or further copies of the same information. Alternatively, we may be entitled to refuse to act on the request in some circumstances.
Please consider your request responsibly before submitting it. We will respond as soon as we can. Generally, this will be within one month from when we receive your request but, if the request is going to take longer to deal with, we will come back to you and let you know.
United States
California Shine the Light. Where applicable, California Civil Code Section 1798.83 allows California residents to request certain information regarding our disclosure of Personal Information to third parties for their direct marketing purposes. To make such a request please contact us using the information provided in the Contact Us section below.
Nevada Residents. If you are a resident of Nevada, you have the right to opt-out of the sale of certain Personal Information to third parties who intend to license or sell that Personal Information. You can exercise this right by contacting us at [Support@galxe.com](mailto:Support@galxe.com) with the subject line “Nevada Do Not Sell Request” and providing us with your name and the email address associated with your account. Please note that we do not currently sell your Sumsub Information as sales are defined in Nevada Revised Statutes Chapter 603A. If you have any questions, please contact us as set forth below.
Contact Us
If you have any concern about our privacy practices, please contact us by email at [Support@galxe.com](mailto:Support@galxe.com).
# Galxe Passport Terms of Use
Source: https://docs.galxe.com/about/legal/passport-terms-of-use
Effective Date: March 1, 2025
TERMS OF USE
Effective Date: March 1, 2025
Hello, and welcome to GALXE Passport. These Terms of Use (“Terms”) describe your rights and obligations when using the Services (defined below) offered by us or our affiliates.Please note that these Terms contain Indemnification, Governing Law, Dispute Resolution, Assumption of Risk and Disclaimer of Warranties and Limitation of Liability Sections that affect your rights, including your ability to bring legal claims against us. Please read these Terms, our Privacy Policy and any other terms referenced in this document carefully. If you do not agree to be bound by these Terms, you are not permitted to use our Services.
1. Introduction
GALXE Passport is a Know Your Customer (“KYC”) identity-verification tool that allows users to authenticate their identity and create a shareable Non-Fungible Token to use with other Web3 platforms, and is operated by Star Frameworks Labs Pte. Ltd. (“GALXE”, “we”, “us”, “our”). These Terms govern your access to and use of the GALXE Passport website [https://galxe.com/passport](https://galxe.com/passport) (“Website”) and any other related and connected platforms or services (collectively, the “Services”). By accessing the Services, you agree that you have read, understand, and accept all of the terms and conditions contained in these Terms, including Section 12 ("Dispute Resolution"), as well as the Privacy Policy.
2. Using Our Services
Eligibility. To be eligible to use the Services the jurisdiction in which you access the Service must allow these Services and you must be of the legal age in the jurisdiction you reside in at the time of using the Services. If you are below the legal age in your jurisdiction, you are prohibited from using the Services. If any part of the Services is prohibited in your jurisdiction, you are prohibited from using those Services.
Updates to Terms of Use. Your use of the Services is subject to your agreement to these Terms, which may be updated by us at any time with or without notice to you. The Effective Date of the most up to date Terms will be provided at the top of each version of these Terms, respectively. Any such updates will be effective upon our publishing such updated Terms. If you do not agree with these Terms, you may not use the Services.
Service Users. By using our Services you are a service user (“Service User"). By becoming a Service User, you agree: (a) to provide accurate, current and complete information about yourself; (b) to maintain and promptly update from time to time. As necessary your information; (c) to immediately notify us if you discover or otherwise suspect any security breaches related to the Services; and (d) that you are fully responsible for all activity on the Services that occurs under your email and password combination. We may, in our sole discretion, refuse to allow you to become a Service User, or limit the number of User Accounts or GALXE Passport NFT (as defined below) that you may associate with the Services, or suspend or terminate any Service User or User Account,including access to our Services.
You also agree that you will not:
* Use the Services if we've disabled access for you, unless you have our written permission first;
* Buy, sell, rent or lease access to your GALXE Passport NFT (as defined below) to any third party; or
* Use or access the Services through any unauthorized third party application(s) or client(s).
User Accounts. In order to create a GALXE Passport NFT, Service Users may need to create a User Account and provide Identity Documents (as defined below). To create a user account ("User Account”) with GALXE, you need to connect your digital wallet to the Services. Once you create a User Account, you will then need to verify your identity by providing certain information and uploading a picture of themselves and a picture of their passport, driver's license, national insurance card, or other government-issued identification (collectively, “Identity Documents”). Once your identity has been verified, you will be able to mint the GALXE Passport NFT.
Account Communication. By becoming a Service User, you consent to receive electronic communications from us (e.g., via email, push notification, or by posting notices to the Services, etc.). These communications may include notices about your use of the Services (e.g., email changes and/or other transactional information) and are part of your relationship with us.
Account Verification and Additional Information. GALXE may require you to provide additional information and documents at the request of any competent authority or in case of application of any applicable law or regulation, including laws related to anti-laundering (or so-called “legalization”) of incomes obtained by criminal means, or for counteracting the financing of terrorism. GALXE may also require you to provide additional information and/or documents in cases where it has reason to believe that:
* Your use of the Services is related to money laundering or any other illegal or illicit activity;
* You have concealed or reported false identification information and/or other details; or
* Transactions effected via your User Account were effected in breach of these Terms.
In such cases, GALXE, in its sole discretion, may pause or cancel your access to any or all Services until such additional information and/or documents are reviewed by us and accepted as satisfying the requirements of applicable law. If you do not provide complete and accurate information and documents in response to such a request, GALXE, in its sole discretion, may refuse to provide the Services to you. Unless otherwise noted in writing, by submitting personal data through our Site or Services, you agree to the terms of the Privacy Policy and you expressly consent to the collection, use and/or disclosure of your personal data in accordance with the Privacy Policy.
3. GALXE Passport NFT
As part of the Services, you are able to create a verified identity token (“GALXE Passport NFT”). You may be required to provide us additional information to create your Token, required to confirm your identity. We work with a third party service provider, Sumsub, to verify your identity. You will upload your information, including identity verification information, to Sumsub, who will then conduct the identity verification. Once your identity is verified, Sumsub will send to us a copy of the information you provided to verify your identity. We will pack the identity information into a verifiable credential, send it to you, and ask you to encrypt it with your password. After you send us the encrypted data, we will keep it safely stored on our servers, and delete all information we collected during the process. At this point, only you can use your password to decrypt and access your identity information.
4. User Conduct
Prohibited Uses. You may not use the Services to engage in the following categories of activity ("Prohibited Uses"). The specific types of use listed below are representative, but not exhaustive, and GALXE reserves the right to update or amend such list in its sole discretion at any time, with or without notice to you. These Prohibited Uses are in addition to the Community Guidelines (discussed below). If you are uncertain as to whether or not your use of the Services involves a Prohibited Use or have questions about how these requirements apply to you, please contact us at [Support@galxe.com](mailto:Support@galxe.com). By becoming a Service User, you agree that you will not use the Services to do or undertake any of the following, as determined by GALXE in its sole discretion:
* Abusive Activity: Actions which: (i) impose an unreasonable or disproportionately large load on our infrastructure, or detrimentally interfere with, intercept, or expropriate any system, data, or information; (ii) transmit or upload any material to the Services that contains viruses, trojan horses, worms or any other harmful or deleterious programs; (iii) attempt to gain unauthorized access to the Services, computer systems or networks connected to the Services, through password mining or any other means; (iv) use the account of any third party to access or use the Services, except in the case of applications which are specifically authorized by a third party to access such third party's User Account and information; or (v) transfer your access or rights to use the Services to a third party, unless by operation of law or with the express permission of GALXE.
* Unlawful Activity: Activity which would violate, or assist in violation of, any law, statute, ordinance or regulation, sanctions programs administered in any of the countries where GALXE conducts business, including but not limited to the U.S. Department of Treasury's Office of Foreign Assets Control ("OFAC"), or which would involve proceeds of any unlawful activity.
* Abuse Other Users: Interfere with another individual's access to or use of the Services; defame, abuse, extort, harass, stalk, threaten or otherwise violate or infringe the legal or other rights (such as, but not limited to, rights of privacy, publicity and intellectual property) of others; or harvest or otherwise collect information from the Services about others, including without limitation email addresses and password, without proper consent.
* Fraud: Activity which operates to defraud GALXE, any GALXE user(s) or any other person, or provide any false, inaccurate, or misleading information to GALXE or to our third-party service providers.
* Copyright violations: Activity which intentionally infringes upon another's copyright, or other intellectual rights, protections, including unauthorized copying or performing of copyrighted works available on the Services.
Your legal obligations. It is possible that your use of the Services may result in certain reporting, tax or other legal obligations on your part. You agree to seek your own advice as necessary, and to comply with any legal obligations you may have in connection with your use of our Services.
5. Service Fees
Fees. Creating GALXE Passport NFTs may be subject to fees and other charges ("Fees") established from time to time in the sole discretion of GALXE, and/or third-party service providers. On the date of initial publication of these Terms, Fees include service fees established by and payable to GALXE. Service fees may be adjusted from time to time in the sole discretion of GALXE.
6. Access to our Services
Suspension, Termination, and Cancellation. GALXE may, at its option and in its sole discretion: (a) suspend or restrict your User Account and/or access to any or all of the Services, and/or (b) deactivate or cancel your User Account and block your access to the Services, if: (i) we are so required by a facially valid subpoena, court order, or binding order of any government authority; (ii) we reasonably suspect you of using the Services in connection with a Prohibited Use; (iii) your use of the Services is subject to any pending litigation, investigation or government proceeding and/or we, in our sole discretion, perceive a heightened risk of legal or regulatory non-compliance associated with your activity; (iv) any of our service partners are unable to support your use thereof; (v) you take any action that GALXE deems in its sole discretion as circumventing GALXE's controls, or abusing promotions which GALXE may offer from time to time; or (vi) you breach these Terms.
Notice to You. If GALXE suspends or closes your account or terminates your use of the Services for any reason, we will provide you with notice of our actions, unless a court order or other legal process prevents or prohibits GALXE from providing you with such notice. You acknowledge that GALXE's decision to take certain actions, including limiting access to, suspending, or disassociating your GALXE Passport NFT from the Services, may be based on confidential criteria that are essential to GALXE's risk management and/or security protocols. You agree that GALXE is under no obligation to disclose the details of its risk management and/or security procedures to you.
7. Copyright and License to You
Information Ownership. Unless otherwise indicated in writing by us, the Services and all content and other materials contained therein, including, without limitation, the GALXE Passport logo and all designs, text, graphics, pictures, information, data, software, sound files and/or other files related thereto and/or associated therewith and the selection and arrangement thereof (collectively, “Content”) are and shall remain the sole and proprietary property of GALXE and/or our affiliates or licensors, including the developers, if and as applicable. If you print, copy, modify, download or otherwise use or provide any other person with access to any part of the Services in breach of these Terms, your right to use the Services will terminate immediately and you must, at our option, either return or destroy any Content you have copied, downloaded, or otherwise obtained from the Services. No right, title or interest in or to the Services or any Content thereon is or shall be transferred to you, and all rights not expressly granted herein are reserved byGALXE and/or its affiliates. Any use of the Services not expressly permitted by these
Terms shall be deemed a material breach of these Terms and may violate copyright, trademark and/or other laws.
Third Party Intellectual Property. Notwithstanding anything to the contrary in these Terms, the Services and Content may include software components provided by GALXE or its affiliates or a third party that are subject to separate license terms, in which case those license terms will govern the usage of such software components, as applicable.
Limited License to You. These Terms grant users a limited and non-exclusive right to use the Services, including all Content thereon. Except as indicated otherwise herein or in any additional terms or conditions, you may not reproduce, distribute, modify, create derivative works of, publicly display, publicly perform, republish, download, store, transmit or otherwise exploit any of the Content on our Services, except as follows
* Your device may temporarily store copies of such materials in RAM incidental to your accessing and viewing those materials.
* You may store files that are automatically cached by your web browser for display enhancement purposes.
* If we provide any so-called “social media” features as part of the Services, you may take such actions as are enabled by such features and are consistent with these Terms.
You must not:
* Modify copies of any Content from the Services.
* Use any illustrations, photographs, video or audio sequences or any graphics available through the Services separately from the accompanying text.
* Delete or alter any copyright, trademark or other proprietary rights notices from copies of materials available through the Services. If you wish to make any use of Content other than that set out in this Section, please address your request to: [Support@galxe.com](mailto:Support@galxe.com).
Third Party Services. The Services may contain links to third-party websites (“Third- Party Websites”) and/or applications (“Third-Party Applications”). When you click on a link to a Third-Party Website or Third-Party Application, we will not warn you that you have left the Services and are subject to the terms and conditions (including privacy policies, if and as applicable) of another website or destination. Such Third-Party Websites and Third-Party Applications are not under the control of GALXE. GALXE is not responsible for any Third-Party Websites or Third-Party Applications and shall not be liable with respect to any use thereof. GALXE provides these Third-Party Websites and Third-Party Applications only as a convenience and does not review, approve, monitor, endorse, warrant or make any representations with respect to Third-Party Websites or Third-Party Applications or their products or services. You use all links in Third-Party Websites, and Third-Party Applications at your own risk. When you leave our Services, these Terms and any of our other policies no longer govern. You should review all applicable agreements and policies, including privacy and data gathering practices, of any Third-Party Websites or Third-Party Applications, and should make whatever investigation you feel necessary or appropriate before proceeding with any transaction with any third party.
Links to our Services. You are granted a limited, nonexclusive, nontransferable right to create a text hyperlink to the Services for noncommercial purposes, provided that such link does not portray GALXE or our affiliates or any of our products or services in a false, misleading, derogatory or otherwise defamatory manner, and does not imply that GALXE is affiliated with or supports or endorses any product or service, and provided further that the linking site does not contain any adult or illegal material or any material that may be deemed, in GALXE's sole discretion, offensive, harassing or otherwise objectionable. This limited right may be revoked or modified by us at any time, for any reason. You may not use a logo or other proprietary graphic or intellectual property of GALXE to link to the Services or Content without our express written permission. Further, you may not use, frame or utilize framing techniques to enclose any GALXE trademark, logo or other proprietary information, including the images found on the Services, the content of any text or the layout or design of any page, or form contained on a page, on the Services without our express written permission.
Trademark. The GALXE Passport logo and any GALXE product or service names, logos or slogans that may appear on the Services are trademarks of GALXE or our affiliates and may not be copied, imitated or used, in whole or in part, without our prior express written permission. You may not use any so-called “metatags” or other "hidden text” utilizing “GALXE Passport” or any other name, trademark or product or service name of GALXE or our affiliates without our prior written permission. In addition, the look and feel of the Services and Content, including, without limitation, all page headers, custom graphics, button icons and scripts, constitute the service mark, trademark or trade dress of GALXE and may not be copied, imitated or used, in whole or in part, without our prior written permission. All other trademarks, registered trademarks, product names and GALXE names or logos mentioned on the Services are the property of their respective owners and may not be copied, imitated or used, in whole or in part, without the permission of the applicable trademark holder. Reference to any products, services, processes or other information by name, trademark, manufacturer, supplier or otherwise does not constitute or imply endorsement, sponsorship or recommendation by GALXE.
8. Indemnification
To the fullest extent permitted by applicable law, you agree to indemnify, defend and hold harmless GALXE, and our respective past, present and future employees, officers, directors, contractors, consultants, equity holders, suppliers, vendors, service providers, parent companies, subsidiaries, affiliates, agents, representatives, predecessors, successors and assigns (individually and collectively, the “GALXE Parties"), from and against all actual or alleged claims, damages, awards, judgments, losses, liabilities, obligations, penalties, interest, fees, expenses (including, without limitation, attorneys' fees and expenses) and costs (including, without limitation, court costs, costs of settlement and costs of pursuing indemnification and insurance), of every kind and nature whatsoever, whether known or unknown, foreseen or unforeseen, matured or unmatured, suspected or unsuspected, in law or equity, whether in tort, contract or otherwise (collectively, “Claims”), including, but not limited to, damages to property or personal injury, that are caused by, arise out of or are related to (a) your use or misuse of the Services, (b) any feedback you provide, (c) your violation of these Terms, and/or (d) your violation of any right(s) of any third party. You agree to promptly notify GALXE of any Claim(s) and shall cooperate fully with the GALXE Parties in defending such Claims. You further agree that the GALXE Parties shall have control of the defense or settlement of any third party Claims. THIS INDEMNITY IS IN ADDITION TO, AND NOT IN LIEU OF, ANY OTHER INDEMNITIES SET FORTH IN ANY WRITTEN AGREEMENT(S)BETWEEN YOU AND GALXE.
9. Disclaimers
EXCEPT AS EXPRESSLY PROVIDED TO THE CONTRARY IN A WRITING BY GALXE, THE SERVICES, CONTENT CONTAINED THEREIN, AND ANY DIGITAL ASSET(S) LISTED THEREIN ARE PROVIDED ON AN "AS IS" AND "AS AVAILABLE" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. GALXE (AND ITS AFFILIATE(S), LICENSOR(S) AND/OR OTHER BUSINESS ASSOCIATE(S)) MAKE NO WARRANTY THAT THE SERVICES: (A) WILL MEET YOUR REQUIREMENTS; (B) WILL BE AVAILABLE ON AN UNINTERRUPTED, TIMELY, SECURE OR ERROR-FREE BASIS; OR (C) WILL BE ACCURATE, RELIABLE, COMPLETE, LEGAL OR SAFE. GALXE DISCLAIMS ALL OTHER WARRANTIES OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT AS TO THE SERVICES OR CONTENT CONTAINED THEREIN. GALXE DOES NOT REPRESENT OR WARRANT THAT CONTENT ON THE SERVICES IS ACCURATE, COMPLETE, RELIABLE, CURRENT OR ERROR-FREE. WE WILL NOT BE LIABLE FOR ANY LOSS OF ANY KIND FROM ANY ACTION TAKEN IN RELIANCE ON MATERIAL OR INFORMATION CONTAINED ON THE SERVICES. WHILE GALXE ATTEMPTS TO MAKE YOUR ACCESS TO AND USE OF THE SERVICES AND CONTENT SAFE, GALXE CANNOT AND DOES NOT REPRESENT OR WARRANT THAT THE SERVICES, CONTENT OR OUR SERVERS IS/ARE FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS. WE CANNOT GUARANTEE THE SECURITY OF ANY DATA THAT YOU DISCLOSE ONLINE. YOU ACCEPT THE INHERENT SECURITY RISKS OF PROVIDING INFORMATION AND DEALING ONLINE OVER THE INTERNET AND WILL NOT HOLD US RESPONSIBLE FOR ANY BREACH OF SECURITY UNLESS IT IS DUE TO OUR GROSS NEGLIGENCE. WE WILL NOT BE RESPONSIBLE OR LIABLE TO YOU FOR ANY LOSS AND TAKE NO RESPONSIBILITY FOR, AND WILL NOT BE LIABLE TO YOU FOR, ANY USE OF ANY DIGITAL ASSETS OR NFT CONTENT, INCLUDING BUT NOT LIMITED TO ANY LOSSES, DAMAGES OR CLAIMS ARISING FROM: (A) USER ERROR, SUCH AS FORGOTTEN PASSWORDS, PRIVATE KEYS OR SEED PHRASES, INCORRECTLY CONSTRUCTED TRANSACTIONS OR MISTYPED ADDRESSES; (B) SERVER FAILURE OR DATA LOSS; (C) CORRUPTED WALLET FILES; (D) UNAUTHORIZED ACCESS TO APPLICATIONS; OR (E) ANY UNAUTHORIZED THIRD PARTY ACTIVITIES, INCLUDING WITHOUT LIMITATION THE USE OF VIRUSES, PHISHING, BRUTEFORCING OR OTHER MEANS OF ATTACK AGAINST THE SERVICES OR ANY DIGITAL ASSET(S). GALXE is not responsible for sustained casualties due to vulnerability or any kind of failure, abnormal behavior of any software provided by third-party service providers (e.g.,identity verification services), blockchain(s) or any other feature(s) of the Services. GALXE is not responsible for casualties due to any late reporting by developers or representatives (or not reporting at all) of any issues with the blockchain(s) supporting any of the Digital Asset(s), including forks thereof, technical node issues or any other issues that result in any loss of fundsNothing in these Terms shall exclude or limit liability of either party for fraud, death or bodily injury caused by gross negligence, violation of laws, or any other activity that cannot be limited or excluded by legitimate means.
SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES IN CONTRACTS WITH CONSUMERS, SO THE ABOVE EXCLUSION MAY NOT APPLY TO YOU, SOLELY TO THE EXTENT SUCH EXCLUSION IS SO PROHIBITED BY APPLICABLE LAW.
10. Assumption of Risk
Digital Assets / Cryptocurrency. The Services involve and/or rely upon certain blockchain technology, including decentralized, distributed public ledger(s), which offer many benefits, but also presents certain inherent risks that you assume by using the Services, including without limitation, that:
* A lack of use or public interest in the creation and development of distributed ecosystems could negatively impact the development of those ecosystems and related applications, and could therefore also negatively impact the potential utility of Digital Asset(s).
* The regulatory regime governing blockchain technologies, digital assets, cryptocurrencies and/or so-called “tokens” is uncertain, and new regulations or policies may adversely affect the development of the Services and/or the utility of Digital Asset(s).
11. Limitation of Liability
TO THE FULLEST EXTENT PROVIDED BY LAW, IN NO EVENT WILL GALXE OR ITS AFFILIATES, OR ITS OR THEIR LICENSORS, SERVICE PROVIDERS, EMPLOYEES, CONTRACTORS, AGENTS, OFFICERS OR DIRECTORS, BE LIABLE FOR ANY INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES, INCLUDING BUT NOT LIMITED TO, PERSONAL INJURY, PAIN AND SUFFERING, EMOTIONAL DISTRESS, LOSS OF REVENUE, LOSS OF PROFITS, LOSS OF BUSINESS OR ANTICIPATED SAVINGS, LOSS OF USE, LOSS OF GOODWILL, LOSS OF DATA, LOSS OF DIGITAL ASSETS, LOSS OF ACCESS TO ANY DIGITAL WALLET, OR ANY OTHER DAMAGES OF ANY KIND, UNDER ANY LEGAL THEORY, ARISING OUT OF OR IN CONNECTION WITH YOUR USE, OR INABILITY TO USE, THE SERVICES, INCLUDING BUT NOT LIMITED TO ANY CONTENT ON THE SERVICES OR ANY OTHER WEBSITES AND MOBILE APPLICATIONS OR ANY ITEMS OBTAINED THROUGH THE SERVICES OR SUCH OTHER WEBSITES AND MOBILE APPLICATIONS, WHETHER CAUSED BY TORT (INCLUDING NEGLIGENCE), BREACH OF CONTRACT OR OTHERWISE, EVEN IF FORESEEABLE. IN NO EVENT WILL OUR AGGREGATE LIABILITY FOR ALL CLAIMS RELATING TO THE SERVICES, THE ACCESS TO AND USE OF THE SERVICE, CONTENT, DIGITAL ASSETS OR ANY PRODUCTS OR SERVICES PURCHASED ON THE SERVICES EXCEED THE GREATER OF (A) \$100 OR (B) THE AMOUNT RECEIVED BY GALXE FROM YOU RELATED TO THE SERVICES THAT ARE THE SUBJECT OF THE APPLICABLE CLAIM. ANY CAUSE OF ACTION OR CLAIM YOU MAY HAVE ARISING OUT OF OR RELATING TO THESE TERMS OR THE SERVICES MUST BE COMMENCED WITHIN ONE (1) YEAR AFTER THE CAUSE OF ACTION ACCRUES, OTHERWISE, SUCH CAUSE OF ACTION OR CLAIM SHALL BE DEEMED PERMANENTLY WAIVED AND BARRED. THIS SECTION DOES NOT AFFECT ANY LIABILITY THAT CANNOT BE EXCLUDED OR LIMITED UNDER APPLICABLE LAW. BECAUSE SOME STATES OR JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR THE LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, IN SUCH STATES OR JURISDICTIONS THE ABOVE LIMITATIONS AND EXCLUSIONS MAY NOT APPLY TO YOU. IN SUCH STATES OR JURISDICTIONS, OUR LIABILITY IS LIMITED TO THE EXTENT PERMITTED BY LAW, THEREBY MINIMIZING OUR LIABILITY TO YOU TO THE LOWEST AMOUNT PERMITTED BY APPLICABLE LAW.
12. Dispute Resolution
This Section includes an arbitration agreement and an agreement that all claims will be brought only in an individual capacity (and not as a class action or other representative proceeding). Please read it carefully. Informal Process. You agree that in the event of any dispute between you and GALXE, you will first contact GALXE in a writing that specifically references this section and which describes the dispute and your position in relation to it in sufficient details for the receiving company to engage in meaningful discussions about the dispute (“Dispute Notice"). For a period of no less than thirty days after receipt of the Dispute Notice, or such longer period as the parties may agree in writing, You shall make a good faith and sustained effort for a to resolve the dispute before resorting to more formal means of resolution.
Agreement to Arbitrate. After the informal dispute resolution process, any remaining dispute arising out of or in connection with these Terms or GALXE's services and/or products, including but not limited to the Services, or relating in any way to the communications between you and GALXE or any other user of the Services, including any question regarding its existence, validity or termination (collectively, “Dispute”), shall be referred to and finally resolved by arbitration before a sole arbitrator in an arbitration administered by the Singapore International Arbitration Centre (“SIAC") in accordance with the Arbitration Rules of the Singapore International Arbitration Centre ("SIAC Rules") for the time being in force, which rules are deemed to be incorporated by reference in this clause. You and GALXE shall endeavor to agree upon the arbitrator, and if you and GALXE fail to do so within twenty-one (21) days of the commencement of the Arbitration, the appointment shall be made by SIAC in accordance with the SIAC Rules. This mandatory arbitration agreement applies to you and to GALXE. However, this arbitration agreement does not (a) govern any Dispute initiated by GALXE for infringement of its intellectual property, or (b) bar you from making use of applicable small claims court procedures in appropriate cases. The seat, or legal place of arbitration, shall be \[Singapore], and the language of the arbitration shall be English. This arbitration provision will survive any termination of these Terms. If you wish to begin an arbitration proceeding, after following the informal dispute resolution procedure, you must send a letter requesting arbitration and describing your claim to: [Support@galxe.com](mailto:Support@galxe.com)
Arbitration Procedure and Rules. The arbitration will be administered by the SIAC under the SIAC Rulesby a sole arbitrator. You can access the SIAC Rules at [https://siac.org.sg/our-rules](https://siac.org.sg/our-rules). Each party shall bear its own filing and administrative fees in the first instance. GALXE will reimburse those fees for claims where the amount in dispute is less than \$10,000, unless the arbitrator determines the claims are frivolous, and we will not seek attorneys' fees and costs in arbitration unless the arbitrator determines the claims are frivolous. The arbitrator, and not any federal, state or local court, will have exclusive authority to resolve any dispute relating to the interpretation, applicability, unconscionability, arbitrability, enforceability or formation of this arbitration agreement, including any claim that all or any part of this arbitration agreement is void or voidable. However, the preceding sentence will not apply to the "Class Action Waiver” section below.
Class Action Waiver. Any Claim must be brought in the respective party's individual capacity, and not as a plaintiff or class member in any purported class, collective, representative, multiple plaintiff or similar proceeding (“Class Action").
The parties expressly waive any ability to maintain any Class Action in any forum. If the Claim is subject to arbitration, the arbitrator will not have authority to combine or aggregate similar claims or conduct any Class Action nor make an award to any person or entity not a party to the arbitration. Any claim that all or part of this Class Action Waiver is unenforceable, unconscionable, void or voidable may be determined only by a court of competent jurisdiction and not by an arbitrator. The parties understand that any right to litigate in court, to have a judge or jury decide their case or to be a party to a class or representative action is waived, and that any claims must be decided individually, through arbitration.
Waiver of Jury Trial. If for any reason a claim proceeds in court rather than in arbitration, you and GALXE each waive any right to a jury trial.
13. Miscellaneous
Governing Law and Venue. These Terms, your access to and use of the Services and Content, and your participation in the Services, shall be governed by and construed and enforced in accordance with the laws of Singapore.
Severability. If any term, clause or provision of these Terms is held invalid or unenforceable, then that term, clause or provision will be severable from these Terms and will not affect the validity or enforceability of any remaining part of that term, clause or provision, or any other term, clause or provision of these Terms.
Waiver. If we fail to insist that you perform any of your obligations under these Terms, or if we do not enforce our rights against you, or if we delay in doing so, that will not mean that we have waived our rights against you and will not mean that you do not have to comply with those obligations. If we do waive a default by you, we will only do so in writing, and that will not mean that we will automatically waive any later default by you.
Assignability. These Terms are personal to you, and are not assignable, transferable or sublicensable by you except with GALXE's express written consent.
Notices. All notices under these Terms will be in writing and will be deemed to have been duly given when received, if personally delivered or sent by certified or registered mail, return receipt requested; when receipt is electronically confirmed, if transmitted by facsimile or e-mail; or the day after it is sent, if sent for next day delivery by recognized overnight delivery service.
# Galxe Privacy Policy
Source: https://docs.galxe.com/about/legal/privacy-policy
Last Updated: September 10, 2025
This Privacy Policy ("Policy") describes howGlaxe Group Inc., d/b/a Galxe with registered office at Aegis Chambers, 1st Floor, Ellen Skelton Building, 3076 Sir Francis Drake's Highway, Road Town, Tortola, VG1110, British Virgin Islands, and its affiliates (collectively, "Galxe" "we" "us" or "our") collects, uses, and discloses information related to the users of the website [https://app.galxe.com/("Website](https://app.galxe.com/\("Website)") and/or our mobile application ("App"), if offered, and any other related and connected platforms and other online and offline interactions (collectively, the "Services").
Your use of our Services is subject to our Terms of Use, available at [https://gal.xyz/tos](https://gal.xyz/tos), which includes applicable terms governing limitations on liability and the resolution of disputes. By using the Services, you accept and agree to the practices described in this Policy. If you do not agree with this Policy, please do not use the Services or provide us with any Personal Information (as defined below).
### Personal Information
For purposes of this Policy, unless otherwise required by applicable law, "Personal Information" means any information that (directly or indirectly) identifies, relates to, describes, or is reasonably capable of being associated, linked or linkable with a particular individual or household, including any information that is subject to applicable data protection laws.
### Scope
This Policy applies to our collection, use and disclosure of Personal Information related to the users of our Services, and applies to all users of our Services.
### Collection of Personal Information
The Personal Information we collect varies depending upon the nature of the Services provided or used and our interactions with individuals.
Categories of Personal Information. While the Personal Information we collect varies depending upon the circumstances, we may collect the following categories of Personal Information (subject to applicable legal requirements and restrictions):
* Name, contact information and other identifiers: identifiers such as a name, username, account name, X handle, blockchain address, address, phone number, birth date, email address, and online identifier.
* Customer records: electronic customer records containing Personal Information. We may also collect your payment information as well, but note this is processed by our third party payment processor.
* Blockchain information: your wallet address, on-chain activities, interactions with the Services on the blockchain, and other similar activities.
* Device information: internet protocol (IP) address, web browser type, operating system version, phone carrier and manufacturer, application installations, device identifiers, mobile advertising identifiers, and push notification tokens.
* Protected classifications: characteristics of protected classifications under applicable law such as race, sex, age, and disability.
* Communications: direct communication, web forms, online polls, or interactions with our blogs and posts.
* Commercial information: including records of products or services purchased, obtained, or considered, or other purchasing or use histories or tendencies.
* Usage data: internet or other electronic network activity information including, but not limited to, browsing history, search history, and information regarding a consumer's interaction with an Internet website, application, or advertisement.
* Location data: location information about a particular individual or device, general location information (for example, your IP address may indicate your more general geographic region). However, this information is not precise geolocation.
* Profiles and inferences: inferences drawn from any of the information identified above to create a profile reflecting a resident's preferences.
Sources of Personal Information. We may collect Personal Information about individuals:
* Directly from you: such as when you create an online account with us (the "User Account"), associate your blockchain wallet address with a Galxe ID account, input messages into our Chatbots, participate in a transaction, communicate on the Services, participate in contests and promotions we offer, register to receive marketing and other communications from us, or contact us for customer support purposes.
* From third parties: such as affiliate and other third parties, public records, third-party providers of services to us (e.g., fraud detection, identity verification and security), consumer data resellers, social networks, joint marketing partners and affiliate companies.
* Related to your use of our Services: including information we collect automatically when you use our Website or interact with us, or information we derive about you and your preferences or interests based on the Personal Information we collect and our interactions with you.
Information We Collect From You. We may collect Personal Information from you related to:
* Registration, accounts and profiles: when you register for a User Account with us, we collect your blockchain address(es), usernames, and email address; if you chose to connect third party services to your User Account, we collect the information about those third party services; we may also collect additional information such as your preferences and payment details.
* Marketing, surveys and events: if you sign up to receive news, updates, offers and other marketing communications from us, or attend any events hosted by us, we may collect your name, contact information, and information about your preferences.
* Your communications and requests: when you email us, call us, or otherwise send us communications, we collect and maintain a record of your contact details, communications and our responses.
Information We Collect from Third Parties. We may collect Personal Information about you from third-party sources (which may be combined with other Personal Information we have collected about you), such as:
* Third-party accounts: if you connect your third party accounts to your User Account (such as Twitter, Discord, or GitHub), we will collect certain personal information about you from those third parties.
* Purchases, orders and payments: if you purchase an NFT or other blockchain asset, or sign up for certain Services, we collect information in order to process your payment such as your name, billing address, payment type, as well as credit card number or other payment account details (e.g., PayPal).
* Social media: if you choose to link, create, or log in to your User Account with a social media service (e.g., Twitter, Facebook, Instagram, etc.), we collect your permission to access certain information from your profile with that social media service. If you post or if you engage with a separate social media service or interact with us on our page with any social media service, we may collect Personal Information about you related to those interactions.
* Other: we may obtain Personal Information, such as demographic information or updated contact details, from third parties; we may also collect information from public records.
Information We Collect Automatically. We may collect or derive Personal Information about your use of our Services, or other interactions with us.
* Website and App: We and our third-party providers may use cookies, pixels, tags, log-files, and other technologies to collect information about a user from their browser or device, including, without limitation, your browser type, device type, operating system, software version, phone model, phone operating system, platform-dependent information, requested document, referring URL, date and time of your visit, clickstream data (e.g., about the pages you view, links you click and date and time stamps for your activities on our Website), and the IP address associated with your transactions in the system. The information that we collect automatically may be linked with other Personal Information we have collected.
### Use of Personal Information
We will only process your Personal Information where we have legal grounds to do so. We may use Personal Information for a variety of purposes, including, without limitation:
* Providing support and services: including to provide our Services, operate our Website, App and online services, create your Web3 Score, update your Galxe ID information, and interact with you on our Services; to respond to your inquiries; to provide troubleshooting, fulfill your orders and requests, process your payments and provide technical support; and for other customer service and support purposes. Our lawful basis is to fulfil any contractual terms with you.
* Analyzing and improving our business: including to better understand how users access and use our Services, to evaluate and improve our Services and business operations, and to develop new features, offerings, and services; to conduct surveys and other evaluations (such as customer satisfaction surveys); to monitor consumer interest in our products and Services; to troubleshoot problems that may arise on the Services; to improve the accuracy of our customer database; to increase our understanding of our customer database; to increase our understanding of our customers; and for other research and analytical purposes. Our lawful basis is our legitimate business interests in understanding and improving our Services.
* Personalizing content and experiences: including to tailor content we send or display on our Website and other Services and to otherwise personalize your experiences. To assist in these purposes, as well as the other purposes identified in this Policy, at certain times, we create a profile relating to you in order to show you the content that we think you might be interested in and to display the content according to your preferences. Our lawful basis is: 1) our legitimate business interests in offering a more personalized service; and 2) business improvement.
* Advertising, marketing and promotional purposes: including to reach you with more relevant ads and to evaluate, measure and improve the effectiveness of our ad campaigns; to send you newsletters, offers or other information we think may interest you; to contact you about our Services, products, or other information we think may interest you; and to identify potential new customers. Our lawful basis is your consent to choose to subscribe to any newsletter or marketing (and you can unsubscribe at any time).
* Securing and protecting our business: including to protect and secure our business operations, assets, Services, network and information and technology resources; to investigate, prevent, detect and take action regarding fraud, unauthorized access, situations involving potential threats to the rights or safety of any person or third-party, or other unauthorized activities or misconduct. Our lawful basis is our legitimate business interests in protecting our business and services.
* Defending our legal rights: including to manage and respond to actual and potential legal disputes and claims, and to otherwise establish, defend or protect our rights or interests, including in the context of anticipated or actual litigation with third parties. Our lawful basis is our legitimate business interests in protecting our business or our need to defend ourselves legally.
* Auditing, reporting, corporate governance, and internal operations: including relating to financial, tax and accounting audits; audits and assessments of our operations, privacy, security and financial controls, risk, and compliance with legal obligations; our general business, accounting, record keeping and legal functions; and related to any actual or contemplated merger, acquisition, asset sale or transfer, financing, bankruptcy or restructuring of all or part of our business. Our lawful basis is our legal obligations under relevant legislation such as tax reporting and our legitimate interests in running our governance programs.
* Complying with legal obligations: including to comply with the law, our legal obligations and legal process, such as warrants, subpoenas, court orders, and regulatory or law enforcement requests. Our lawful basis is compliance with applicable law.
* For our legitimate business interests: including our business interest in conducting and managing our business and enabling us to give you the best service/product and the best and most secure experience. We make sure we consider and balance any potential impact on you (both positive and negative) and your rights before we process your Personal Information for our legitimate interests. We do not use your Personal Information for activities where our interests are overridden by the impact on you (unless we have your consent or are otherwise required or permitted to by law). You can obtain further information about how we assess our legitimate interests against any potential impact on you in respect of specific activities by contacting us. Our lawful basis is this legitimate business interest.
Aggregate and De-identified Data. We may de-identify information and create anonymous and aggregated data sets and reports to assess, improve and develop our business, products and Services, prepare benchmarking reports on our industry and for other research, marketing and analytics purposes. De-identified information is not Personal Information and we may use de-identified information as allowed under applicable data protection laws.
We may combine information from different sources. For example, we may combine information that we have collected offline with information we collect online, or we may combine information we get from a third-party with information we already have.
If you submit any Personal Information relating to other people to us, you represent that you have the authority to do so and have informed that other person about the contents of this Policy.
### Disclosure of Personal Information
We may share or disclose the Personal Information we collect as follows:
* Service providers: We may disclose Personal Information with third-party service providers who use this information to perform services for us, such as hosting providers, auditors, advisors, consultants, customer service and/or support providers.
* Advertising and Marketing Partners: We may share Personal Information with third parties that provide advertising, campaign measurement, online and/or mobile analytics, and related services. These third parties may receive or access browsing and/or other data about your use of the Services, in order to help us better reach individuals with relevant ads and/or measure our ad campaigns, and/or to better understand how individuals interact with our Services overtime and across devices. We may also transfer and/or sell Personal Information we collect and/or join together with other businesses to bring selected opportunities to customers or potential customers.
* Subsidiaries, affiliates, and business partners: We may share your Personal Information with our affiliated companies (i.e., our parent company and other companies under common ownership, control or management with us; and the Creators we have partnered with to offer exclusive content on our Services); they may use such Personal Information for the purposes set out in this Policy.
* Legal compliance: We may be required to share Personal Information in response to a valid court order, subpoena, government investigation, or as otherwise required by law. We also reserve the right to report to law enforcement agencies any activities that we, in good faith, believe to be unlawful. In addition, we may share certain Personal Information when we believe that doing so is reasonably necessary to protect the rights, property and safety of our company and/or others.
* Business transfers: We may disclose and/or transfer Personal Information as part of any actual or contemplated merger, sale, transfer of assets, acquisition, financing and/or restructuring of all or part of our business, bankruptcy or similar event, including related to due diligence conducted prior to such event where permitted by law.
* Protect our rights: We may disclose Personal Information where we believe it necessary to respond to claims asserted against us, to enforce or administer our agreements and terms, for fraud prevention, risk assessment, investigation and/or to protect the rights, property or safety of Galxe or our affiliates, partners, clients, customers and/or others.
* Aggregated and De-identified Data. We may share aggregate or de-identified information with third parties for research, marketing, advertising, analytics and/or other purposes.
What happens if you do not provide us with the Personal Information we request or ask that we stop processing your Personal Information?
If you do not provide the Personal Information we request, or if you withdraw your consent to the processing of your Personal Information, then you may be unable to use the Services.
### Automated Decisions
Automated decisions are those made without human intervention that have a legal effect on you or other similarly significant effect. We do not carry out this type of processing activity.
### Cookies and Analytics
We use cookies, pixels, tags, and other technologies, which may be provided by third parties, on our Services to enable certain functionality and for security and fraud detection and prevention, as well as to collect usage information about our Website and the emails that we send and to personalize content and provide more relevant ads and information. We may combine the information we collect via these technologies with other information, including Personal Information.
You can find more details in our cookie policy available here: [https://docs.galxe.com](https://docs.galxe.com).
Cookies. Cookies are alphanumeric identifiers that are transferred to your computer through your web browser for record-keeping purposes. Some cookies enable you to log-in to our Services or save certain settings and preferences, while others allow us to track usage and activities on our Services, personalize content, or deliver more relevant ads. Most web browsers automatically accept cookies, but if you prefer, you can edit your browser options to block them in the future. The "Help" tab on the toolbar on most browsers will tell you how to prevent your computer from accepting new cookies, how to have the browser notify you when you receive a new cookie, or how to disable cookies altogether. If you block cookies, however, certain features on our Website may not be available or function properly.
Third parties may use cookies and other similar technologies to collect or receive information from our Site and elsewhere on the Internet and use that information to provide you with targeted ads. If you would like to opt-out of such advertising practices on the particular device on which you are accessing this Privacy Policy, please go to [http://optout.aboutads.info/](http://optout.aboutads.info/). The Network Advertising Initiative also offers a means to opt-out of a number of advertising cookies. Please visit [http://www.networkadvertising.org](http://www.networkadvertising.org) to learn more. Note that opting-out does not mean you will no longer receive online advertising. It does mean that the company or companies from which you opted-out will no longer deliver ads tailored to your preferences and usage patterns.
Pixel tags and embedded script (aka clear GIFs and web beacons). Pixel tags are tiny graphics with a unique identifier, similar in function to cookies. In contrast to cookies, which are stored on your computer's hard drive, pixel tags are embedded invisibly on web pages. We may use these, in connection with our Website to, among other things, track the activities of the users of our Services, improve ads, personalize and manage content, and gather usage information about our Website. We may also use these in HTML emails to help us track email response rates, identify when our emails are viewed, and track whether our emails are forwarded.
Third-Party Analytics Tools. Our Website uses automated devices and applications operated by third parties, such as Google Analytics, which uses cookies and similar technologies to collect and analyze information about use of the Website and report on activities and trends. This service may also collect information regarding the use of other websites, apps and online resources. You can learn about Google's practices by going to [www.google.com/policies/privacy/partners/](http://www.google.com/policies/privacy/partners/), and you can opt out of them by downloading the Google Analytics opt-out browser add-on, available at [https://tools.google.com/dlpage/gaoptout](https://tools.google.com/dlpage/gaoptout).
### Children's Privacy
Our Services are restricted for users of legal age and children under the age of 18 are not allowed to use our Services. Galxe does not knowingly collect or maintain Personal Information from children we actually know at the time of collection are under the age of 18. Should we discover that we have collected Personal Information online from a child who is under 18, we will promptly delete that Personal Information. If you have concerns over the collection of children's Personal Information on the Services, please contact us at the information provided in the Contact Us section below. Although our Services are not directed to children under the age of 18, if your child uses our Services and you wish to review or delete your child's Personal Information, you may so request by contacting us at the location or email address set forth below under 'Contact Us.'
### Security
The security of your Personal Information is important to us. We have put in place safeguards to protect the Personal Information we collect from unauthorized access, use and disclosure, and we take steps to ensure that all of our employees, agents, contractors and other third parties have similar adequate measures in place. We also have procedures to deal with any suspected Personal Information breach, and we will notify you and any applicable regulator when we are legally required to do so. However, we cannot guarantee that unauthorized access, hacking, data loss, or other breaches will never occur. We urge you to take steps to keep your Personal Information safe, such as choosing a strong password and logging out of your User Account and closing your web browser when finished using the Services.
### Transfers outside the UK/Europe
For users in the UK and European Economic Area ("EEA"). We may sometimes transfer your Personal Information to countries outside the UK and EEA, for example if we are using a supplier based elsewhere. The privacy laws in countries outside the UK and EEA may be different from those in your home country.
Where we transfer data to a country that has not been deemed to provide adequate data protection standards, we will always have security measures and approved European or UK model clauses (available on the European Union's legal website at eur-lex.europa.eu and the UK ones at the ICO website [www.ico.gov.uk](http://www.ico.gov.uk)) or other adequate safeguards in place to protect your Personal Information. Please contact us if you would like more details about our safeguards for data transfers outside of the UK/EEA.
For other users. If we transfer your Personal Information to countries outside of your home country, we will take steps to comply with the requirements for such transfer in your home country as required by relevant law.
### Links to Third-party Websites
The Services provide links to various websites operated by third parties including, but not limited to, third-party sites that may display Galxe trademarks. This Policy does not apply to third-party websites that are accessible through the Services, unless such website directs users or visitors to this Policy. When you click on one of these links, you will be transferred out of the Services and connected to the website of the organization or company that maintains that website. Even if an affiliation exists between us and a third-party website, we exercise no control over linked websites. Each of these linked websites maintains its own independent privacy and data collection policies and procedures. We encourage you to read the privacy policies of those other websites to learn how they collect, use, share, and secure your information before providing any Personal Information.
### Retention
Except to the extent prohibited by law, and subject to this Policy, we will retain and use your Personal Information for as long as it is needed to provide you with any services, communications, information you have requested, or access to the Website, to document our business relationship with you, and as necessary to comply with our legal obligations, resolve disputes, and enforce our agreements. As soon as it is reasonable to assume your Personal Information is no longer needed or required, we will cease to retain your Personal Information, or remove the means by which the data can be associated with you.
### Changes to this Policy
This Policy is kept under regular review and may be updated from time to time. When we make changes to this Policy, we will change the "Last Updated" date above. If a material change is made to this Policy, we may choose to provide notice to you in advance of such change, such as by posting notice of that change on the first page of this Policy or on our homepage, or by emailing your email address of record with us.
### Changes to your Information
It is important that the information we hold about you is accurate and current. Please keep us informed as soon as possible if your Personal Information changes or is inaccurate during your relationship with us by using the contact details set out below.
### California Shine the Light Law
Under California's "Shine the Light" law (Cal. Civ. Code § 1798.83), California residents who provide us certain personal data are entitled to request and obtain from us, free of charge, information about the personal data (if any) we have shared with third parties during the immediately preceding calendar year for their own direct marketing use. Such requests may be made once per calendar year for information about any relevant third-party sharing in the prior calendar year. California residents who would like to make such a request may submit a request to the contact information provide below. The request should attest to the fact that the requester is a California resident, and provide a current California address. We are only required to respond to a customer request once during any calendar year. Please be aware that not all information sharing is covered by California's "Shine the Light" law and only information sharing that is covered will be included in our response.
### Supplemental Notice for Nevada Residents
If you are a resident of Nevada, you have the right to opt-out of the sale of certain Personal Information to third parties who intend to license or sell that Personal Information. You can exercise this right by contacting us at [Info@Tonohealth.com](mailto:Info@Tonohealth.com) with the subject line "Nevada Do Not Sell Request" and providing us with your name and the email address associated with your account. Please note that we do not currently sell your Personal Information as sales are defined in Nevada Revised Statutes Chapter 603A. If you have any questions, please contact us as set forth below.
### Additional Information for EEA/UK Residents
By law, you have a number of rights when it comes to your Personal Information. Further information and advice about your rights can be obtained from the data protection regulator in your country, and many countries provide a right to lodge a complaint with the regulator.
You may request for a copy of the Personal Information which we hold about you or information about the ways we use or disclose about your Personal Information. You may also ask us to correct or update your Personal Information, or withdraw your consent and request us to stop using or disclosing your Personal Information for any of the purposes stated in this Policy.
You may do so by submitting your request in writing or via email at the contact details provided below.
We usually act on requests and provide information free of charge, but we may charge a reasonable fee to cover our administrative costs of providing the information for baseless or excessive/repeated requests, or further copies of the same information. Alternatively, we may be entitled to refuse to act on the request in some circumstances.
Please consider your request responsibly before submitting it. We will respond as soon as we can. Generally, this will be within one month from when we receive your request but, if the request is going to take longer to deal with, we will come back to you and let you know.
Under European Union and UK regulation, your rights are:
* The right to be informed. You have the right to be provided with clear, transparent and easily understandable information about how we use your Personal Information and your rights. This is why we are providing you with the information in this Policy. If you have any additional questions, for example regarding transfers and locations of data or our legitimate interests basis, please contact us.
* The right of access. You have the right to obtain access to your Personal Information (if we are processing it), and certain other information (similar to that provided in this Policy). This is so you are aware and can check that we're using your Personal Information in accordance with data protection law.
* The right to rectification. This is also known as the 'right to be forgotten' and enables you to request the deletion or removal of your information where there is no compelling reason for us to keep using it. This is not a general right, there are exceptions.
* The right to restrict processing. You have rights to 'block' or suppress further use of your Personal Information. When processing is restricted, we can still store your Personal Information, but we may not use it further. We keep lists of people who have asked for further use of their information to be 'blocked' to make sure the restriction is respected in future.
* The right to data portability. You have the right to object to certain types of processing, including processing for direct marketing or where we are relying on our legitimate interests for processing.
* The right to lodge a complaint. You have the right to lodge a complaint about the way we handle or process your Personal Information with your national data protection regulator. In the UK, this is the Information Commissioner, and details of how to contact the ICO can be found on their website at ico.org.uk.
* The right to withdraw consent. If you have given your consent to anything we do with your Personal Information, you have the right to withdraw your consent at any time (although if you do so, it does not mean that anything we have done with your personal data with your consent up to that point is unlawful). This includes your right to withdraw consent to us using your personal data for marketing purposes.
### Contact Us
If you have any concern about our privacy practices, please contact us by email at [support@galxe.com](mailto:support@galxe.com).
# Staking Terms and Conditions
Source: https://docs.galxe.com/about/legal/staking-terms-and-conditions
Last Updated: April 23, 2024
By directly or indirectly accessing or using the Website and/or Services (each, as defined below), including, but not limited to, indirectly linking your Digital Wallet (defined below) to the Services or otherwise using the Website or Services or any portion thereof, you hereby consent to be bound by these terms and conditions (“Terms”). These Terms are entered into, and create a legally binding agreement, by and between you, and any organization you are acting on behalf of (“you” or “your”) and Star Frameworks Labs Pte Ltd., d/b/a Galxe, a Singapore company (“Galxe”, “we,” “our,” or “us”). We may amend or modify these Terms at any time and for any reason. The amended or modified Terms are effective immediately upon us posting them or otherwise making them available on \[URL] (“Website”) and by continuing to link your Digital Wallet to our Services, or otherwise use our Services, you agree to such amended or modified Terms. You agree to be responsible for reviewing the Terms and any amendments or modifications thereto. If you do not agree with the Terms, your sole and exclusive remedy is to cease your use of the Services and/or Website.
THESE TERMS CONTAIN IMPORTANT INFORMATION, INCLUDING A BINDING ARBITRATION PROVISION AND A CLASS ACTION WAIVER, BOTH OF WHICH IMPACT YOUR RIGHTS AS TO HOW DISPUTES ARE RESOLVED.
1. Definitions. The definitions for certain defined terms used in these Terms are set out below. Other terms are defined elsewhere in these Terms.
1.1 “Digital Assets” means any digital blockchain asset subject to the Services, including the G token.
1.2 “Digital Wallet” means the wallet or similar device or software used to store Digital Assets.
1.3 “Net Reward” means the sum of the Rewards minus any Protocol Fees (if any).
1.4 “Rewards” means any rewards granted by the Supported Staking Protocol, including staking rewards, block rewards, and transaction fees, in each case as actually granted by such Supported Staking Protocol, as applicable.
1.5 “Protocol Fees” means any fees charged by the Supported Staking Protocol.
1.6 “Supported Asset” means a Digital Asset for which you can use to participate in staking services via the Services.
1.7 “Supported Staking Protocol” means the G token protocol or other staking, delegation or other validator node or staking smart contract that is made available via the Services from time to time.
2. Services
2.1 The Services. Subject to these Terms, we provide a front-end user interface to allow users to connect to the Supported Staking Protocol for Supported Assets (the “Services”). The Services are strictly offered on a non-custodial basis. You hereby agree and acknowledge that (a) Galxe does not at any time hold or custody any assets on your behalf, and (b) Galxe solely offers a front-end user interface for you to interact with third party Supported Staking Protocols, none of which are controlled by Galxe.
2.2 License to Access the Services. Subject to these Terms, we hereby grant you a limited, non-exclusive, revocable, non-transferable, non-sublicensable right and license to access and use the Services for purposes of staking Supported Assets to the Supported Staking Protocol accessible via our Services.
2.3 Blockchain Events. You acknowledge and agree that the Supported Staking Protocols are independently and separately operated and controlled by third parties. As such, at any time and for any reason, the Supported Staking Protocol may modify its protocol, stake or unstake, bond or unbond your Digital Assets, fork, or implement any other action or change that may impact your Net Rewards, Supported Assets, the Services and/or your access to and use of each of the foregoing (together, a “Blockchain Event”).
2.4 Protocol Lockups and Unstaking. Some Supported Staking Protocols require that your Digital Assets be locked (restricted from sale or transfer) for a period of time while staking or unstaking, such as 7 days for the G protocol. You will need to request for your staked Digital Assets to be unstaked before they can be sold or transferred. Depending on the underlying protocol, you may or may not receive staking rewards during the unstaking process. Expected unstaking periods are estimates only. We will notify you when the unstaking process is complete.
2.4 Changes to the Services. We reserve the right to modify, alter or otherwise change the Services from time to time by adding, deleting, or otherwise modifying features or functionality to improve your experience, comply with applicable regulations and/or laws or for any other reason or purpose. We further reserve the right to (i) discontinue any feature of the Services or any portion thereof at any time, including, without limitation, discontinue supporting any Supported Asset, or Supported Staking Protocol, or (ii) remove any content from the Services at any time, in each case for any reason in our sole discretion and without notice to you. You specifically acknowledge and agree that we are not (a) responsible for such modifications, changes, content removals, or (b) liable for any loss of value of your Digital Assets or loss of Net Rewards that may result directly or indirectly from any such changes or any Blockchain Event.
3. Rewards; Fees
3.1 Rewards. Your use of the Services may result in a Net Reward that is issued by the Supported Staking Protocol and either (a) transferred to the Digital Wallet address where your Supported Assets originated or is otherwise used by you in connection with the Services (the “Originating Wallet”), or (b) eligible to be claimed by you using the Originating Wallet. You acknowledge that (i) such Net Rewards may be issued in the same denomination as the Supported Assets, (ii) any estimates or projections of Rewards or Net Rewards, as applicable, are not a guarantee, (iii) we will never ask for and you should never provide to us the private key for your Originating Wallet or any other wallet, (iv) we are not responsible for the loss of your private key or your inability to access (a) your Originating Wallet, or (b) any resulting Net Rewards that may be stored or claimable therein, and (v) you assume responsibility for ensuring the proper use of the correct and valid address of your Originating Wallet(s), and that your Originating Wallet supports and is otherwise compatible with the Supported Asset and Supported Staking Protocol. You specifically acknowledge and understand that your Net Rewards may be subject to a bonding/unbonding, locking/unlocking, claim or other delay period or mechanism by the Supported Staking Protocol that may render your Net Rewards and/or Supported Assets unavailable and/or subject to other restrictions imposed and controlled by the Supported Staking Protocol (collectively, “Protocol Restrictions”).
3.2 Fees. In consideration for granting you a limited license to access and use our Services, you hereby agree that we may charge a service fee.
4. Termination
4.1 Termination. In the event that you breach these Terms or if we reasonably determine that action is necessary or advisable under applicable law, we may terminate or suspend your right to use or otherwise access the Services with or without notice to you. Such termination or suspension shall be a non-exclusive remedy for your breach of these Terms and we reserve the right to pursue any and all additional remedies that may be available to us. We may also terminate or suspend the Services in whole or in part for whatever reason and at any time.
4.2 Effects of Termination. In the event of any termination or suspension pursuant to Section 4.1 or otherwise, the Services will immediately cease. Termination or suspension of the Services may require you or us to complete certain additional tasks that comprise part of the Services, including, but not limited to, your compliance with certain Protocol Restrictions. The performance of such tasks shall be at our discretion and you disclaim any responsibility or obligation that we may have to perform such tasks.
4.3 Survival. The following Sections shall survive termination of these Terms: Section 3.2 (Fees), Section 4.2 (Effects of Termination), Section 5 (Intellectual property), Section 7 (Disclaimer), Section 8 (Limitation of Liability), and Section 9 (Indemnification).
5. Intellectual property
5.1 Ownership. As between you and us, we own all rights, title, and interest in and to the Services and Website and any modifications, improvements, adaptations, enhancements, derivates thereto and any intellectual property rights related thereto, including, but not limited to, patent rights, trademark rights, copyrights, and trade secret rights and any other intellectual property and/or industrial rights recognized anywhere in the world.
5.2 No Other Right. Except for the limited license granted to you in Section 2.2, we do not grant or convey to you by implication, waiver, estoppel or otherwise any license to, any right, title, or interest in and to our intellectual property rights in or to the Services and Website or any other products, software or technology shared or made available by us under or in connection with these Terms.
5.3 No Reverse Engineering; Restrictions. You agree not to, directly or indirectly, (i) copy modify, reproduce, reverse engineer, decompile, disassemble, or otherwise attempt to discern the source code or any other proprietary information or materials related to the Services or the Website; (ii) use the Services or Website to (a) build a competitive product, software or other technology that could be used to offer similar services as to those offered hereunder, (b) engage in activity that seeks to defraud us or any other person or entity, including but not limited to, providing any false, inaccurate or misleading information in order to unlawfully obtain the property of another, or (c) engage in activity that breaches these Terms; (iii) interfere with the Services or Website, their security, network and the operability of any of the foregoing; or (iv) introduce, post, or upload, (a) bugs, time bombs, time locks, traps, trojan horses, or (b) any other harmful code or software that can corrupt or damage data, storage media, programs, equipment, or any hardware used in connection with the Services or Website.
6. YOUR REPRESENTATIONS, WARRANTIES AND COVENANTS; ACKNOWLEDGMENT OF RISKS
6.1 Your Representations and Warranties. You represent, warrant and covenant that:
(i) the organization or entity you may be acting on behalf of is duly organized, validly existing, and in good standing under its jurisdiction of organization and has the right to enter into these Terms;
(ii) you have all requisite power and authority to, and no other proceedings on its part are necessary to, execute and deliver these Terms;
(iii) your performance of your duties and obligations under these Terms and in connection with your use of the Services and Website shall comply with all applicable laws, rules, and regulations;
(iv) you and the organization or entity you may be acting on behalf of are not (a) located, incorporated or otherwise established in, or a citizen or resident of any state, country or other jurisdiction that is designated by the U.S. Secretary of State as a country supporting international terrorism, or to which U.S. nationals cannot lawfully engage in transactions as designated by the Office of Foreign Assets Control (“OFAC”), including Cuba, Crimea, Luhansk and Donetsk regions of Ukraine, Democratic People’s Republic of Korea, Iran and Syria, (b) a person found on the OFAC Specially Designated Nationals, Blocked Persons List, or any other consolidated prohibited persons list as determined by any applicable governmental authority (including any such list maintained by the government of the United Kingdom and/or British Virgin Islands), (c) a person identified as a terrorist organization on any other relevant lists maintained by any governmental authority, or (d) a senior foreign political figure, or an immediate family member or close associate of a senior foreign political figure;
(v) you are of legal age in the jurisdiction in which you reside and have the full legal authority and right (a) to be bound to these Terms, and (b) to bind the organization or entity you may be acting on behalf of to these Terms;
(vi) you have the right, title, and interest in and to the Supported Assets used by you in connection with the Services;
(vii) you have all the rights and requisite authority to submit or otherwise provide your Digital Assets, data or any other materials you provide under and in connection with these Terms;
(viii) any assets, including Supported Assets used by you in connection with the Services is not encumbered or restricted in any manner that would prohibit compliance with these Terms;
(ix) you own or otherwise have the right to access and use the Originating Wallet(s) used in connection with the Services;
(x) you understand that the continued ability to provide the Services is dependent on many elements and you understand the risk involved with use of the Services, Website and Supported Staking Protocol;
(xi) you and the organization or entity you may be acting on behalf of are in compliance with all applicable laws and regulations;
(xii) your use of the Services shall not cause us to be in violation of applicable U.S. federal or state or non-U.S. laws or regulations, including, without limitation, anti-money laundering, economic sanctions, anti-bribery or anti-boycott laws or regulations, the U.S. PATRIOT Act, or the various statutes, regulations and executive orders administered by OFAC (“OFAC Regulations”) or any applicable laws, rules and regulations.
(xiii) None of the Supported Assets used by you in connection with the Services relate in any way to (i) the government of any country designated by the United States, or other governmental authority as a country supporting international terrorism, (ii) property that is blocked under any OFAC Regulations or that would be blocked under OFAC Regulations if it were in the custody of a U.S. national, (iii) persons to whom U.S. nationals cannot lawfully export services, or with whom U.S. nationals cannot lawfully engage in transactions under OFAC Regulations, (iv) the government of any country that has been designated as a non-cooperative country or designated by the U.S. Secretary of the Treasury or other governmental authority as a money laundering jurisdiction or (v) directly or indirectly, any illegal activities.
(xiv) you and the organization or entity you may be acting on behalf of have not been convicted of, or agreed to enter into a pretrial diversion or similar program in connection with the prosecution of, a criminal offense involving theft, dishonesty, breach of trust, money laundering, the illegal manufacture, sale, distribution of or trafficking in controlled substances, or substantially equivalent activity in a domestic, military, or foreign court;
(xv) you are solely responsible for the security, custody and control of any Originating Wallets;
(xvi) you will not use the Services or Website in a manner that infringes, misappropriates or otherwise violates the intellectual property rights and privacy rights of any third party;
(xvii) you are not subject to any restriction or prohibition that would limit or prohibit your use of the Service or Website in accordance with these Terms;
(xviii) the Supported Assets used by you in connection with the Services are not derived from, and do not otherwise represent the proceeds of, any activities done in violation or contravention of applicable law or regulations; and (xviii) you will not use the Services or Website in any manner that violates applicable law or regulations.
6.2 Acknowledgment of Risk. You understand and agree that (i) the Website and Services facilitate access to the Supported Staking Protocol, the use of which has many inherent risks and (ii) cryptographic and blockchain-based systems have inherent risks to which you are exposed when using the Website and Services. You further represent that you have a working knowledge of the usage and intricacies of blockchain-based Digital Assets and that you acknowledge and understand that (a) your use of the Services exposes you to considerable risk of loss; (b) there is no guarantee that any Rewards will be issued by any party or any protocol, and you may not earn any Net Rewards; (c) the operation of the Services and any resulting Net Rewards, if any, depends on the Supported Staking Protocols and other services provided by third parties whom we do not control or which no single identifiable person or entity controls, and as such, it may be difficult or impossible to recover any Digital Assets provided to the Supported Staking Protocol if such Digital Assets are lost or stolen; (d) Digital Assets and staking programs, including the Supported Staking Protocol are new technologies that currently face uncertain and evolving regulatory requirements in many jurisdictions; and (e) one or more such jurisdictions may, in the future, adopt laws, regulations or directives that affect one or more Supported Assets and/or Supported Staking Protocol and that may result in sudden changes (x) to the Services or (y) in connection with your Rewards or Supported Assets. For the avoidance of doubt, we specifically disclaim any liability for any losses or damages you experience in connection with any of the foregoing and you agree to assume full responsibility for all of the risks of accessing and using the Website and Services.
7. DISCLAIMER. THE SERVICES, WEBSITE, AND ANY OTHER PRODUCTS, SOFTWARE OR TECHNOLOGY PROVIDED BY US HEREUNDER IS PROVIDED “AS IS” AND “AS AVAILABLE,” AND WE DO NOT MAKE ANY REPRESENTATIONS OR WARRANTIES WITH RESPECT TO THE SAME OR OTHERWISE IN CONNECTION WITH THESE TERMS, AND HEREBY DISCLAIM ANY AND ALL EXPRESS, IMPLIED, OR STATUTORY WARRANTIES, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AVAILABILITY, ERROR-FREE OR UNINTERRUPTED OPERATION, AND ANY WARRANTIES ARISING FROM A COURSE OF DEALING, COURSE OF PERFORMANCE, OR USAGE OF TRADE. WE FURTHER DISCLAIM ANY LIABILITY INCLUDING, BUT NOT LIMITED TO, ANY LOSSES RESULTING FROM OR IN CONNECTION WITH SLASHING PENALTIES.
8. LIMITATION OF LIABILITY. EXCEPT FOR ACTS OF WILLFUL MISCONDUCT OR FRAUD, TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, UNDER NO CIRCUMSTANCE AND REGARDLESS OF THE NATURE OF ANY CLAIM SHALL WE BE LIABLE UNDER THESE TERMS TO YOU FOR ANY CONSEQUENTIAL, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR ENHANCED DAMAGES OR LOST PROFITS, INTEREST, ATTORNEYS’ FEES, COMPUTER FAILURE OR MALFUNCTION, DATA LOSS, LOSS OF GOODWILL, OR REVENUE ARISING OUT OF RELATING TO, OR IN CONNECTION WITH THESE TERMS. TO THE EXTENT OUR LIABILITY IS NOT ALREADY EXCLUDED BY THE FOREGOING SENTENCE, OUR AGGREGATE LIABILITY UNDER OR IN CONNECTION WITH THESE TERMS SHALL OTHERWISE BE LIMITED TO AN AMOUNT EQUAL TO ONE HUNDRED U.S. DOLLARS (\$100).
9. INDEMNIFICATION You shall and hereby agree to indemnify, defend and hold us and our representatives, officers, directors, employees, successors and assignees harmless from and against any losses suffered by us arising from (i) your breach of these Terms, (ii) a breach of your representations and warranties and/or covenants made hereunder, (iii) your use of the Services or Website in violation of these Terms, (iv) your infringement, misappropriation, or violation of the rights of any other person or entity, (v) any content, materials, or information (in any form or medium) that you submit, post, upload, provide, contribute, or make available (or authorize or instruct us to do so) through the Services or Website, and (vi) violation of any law or applicable regulation. If you are obligated to indemnify us, we have the right to control any action if we want and you cannot settle any action without our consent, unless the settlement is only for money damages which you entirely pay.
10. MISCELLANEOUS
10.1 Governing Law. These Terms, your access to and use of the Services and Content, and your participation in the Services, shall be governed by and construed and enforced in accordance with the laws of the Republic of Singapore, without regard to conflict of law rules or principles of the Republic of Singapore, or any other jurisdiction that would cause the application of the laws of any other jurisdiction. Any dispute between the parties that is not subject to arbitration or cannot be heard in court located in the Republic of Singapore.
10.2 Severability. If any provision of these Terms or the application thereof to any person or circumstance is held invalid or unenforceable to any extent, the remainder of these Terms and the application of that provision to other persons or circumstances is not affected thereby, and that provision will be enforced to the greatest extent permitted by applicable laws.
10.3 Waiver. No waiver of any right under these Terms will be of any effect or binding upon anyone unless such waiver is in writing and is signed by an authorized representative of the party so waiving such right. No delay or failure of any party in exercising any right hereunder and no partial or single exercise of any such right will be deemed of itself to constitute a waiver of such right or other rights hereunder.
10.4 No Third-Party Beneficiaries. The provisions hereof are solely for the benefit of the parties and are not intended to, and will not be construed to, confer a right or benefit on any other person.
10.5 Assignment. You shall not assign or transfer (whether by operation of law or otherwise) these Terms (or any rights or obligations hereunder) to a third party.
10.6 Force Majeure. No party will be held liable or responsible to any other party nor be deemed to have breached these Terms for failure or delay in fulfilling or performing any provision hereunder when such failure or delay results from causes beyond the reasonable control of the affected party, which may include embargoes, acts of war (whether declared or not), insurrections, riots, civil commotions, acts of terrorism, strikes, lockouts or other labor disturbances, pandemics, epidemics or acts of God (a “Force Majeure Event”). The affected party will notify the other parties of such Force Majeure Event as soon as reasonably practical and will make every reasonable effort to mitigate the effects of such Force Majeure Event.
10.7 External Sites and Third-Party Content. The Website may contain links to third-party websites or content (“External Sites”). Such External Sites are provided solely as a convenience to you and not as an endorsement by us of the content on such External Sites. The content of such External Sites is developed and provided by others. You should contact the site administrator or webmaster for those External Sites if you have any concerns regarding such links or any content located on such External Sites. We are not responsible for the content of any linked External Sites and do not make any representations regarding the content or accuracy of materials on such External Sites. You should take precautions when (i) interacting with such External Sites, or (ii) downloading files from all websites to protect your computer from viruses and other destructive programs. If you decide to access linked External Sites, you do so at your own risk.
10.8 Arbitration. This Section includes an arbitration agreement and an agreement that all claims will be brought only in an individual capacity (and not as a class action or other representative proceeding). Please read it carefully.
(i) Informal Process. You agree that in the event of any dispute between you and Galxe, you will first contact Galxe and make a good faith sustained effort to resolve the dispute before resorting to more formal means of resolution, including without limitation any court action.
(ii) Agreement to Arbitrate. Any dispute arising out of or in connection with these Terms, including any question regarding its existence, validity or termination, shall be referred to and finally resolved by arbitration administered by the Singapore International Arbitration Centre (“SIAC”) in accordance with the Arbitration Rules of the Singapore International Arbitration Centre (“SIAC Rules”) for the time being in force, which rules are deemed to be incorporated by reference in this clause. The seat of the arbitration shall be Singapore. The Tribunal shall consist of 1 arbitrator. The language of the arbitration shall be English.
10.9 Class Action Waiver. Any Claim must be brought in the respective party’s individual capacity, and not as a plaintiff or class member in any purported class, collective, representative, multiple plaintiff or similar proceeding (“Class Action”). The parties expressly waive any ability to maintain any Class Action in any forum. If the Claim is subject to arbitration, the arbitrator will not have authority to combine or aggregate similar claims or conduct any Class Action nor make an award to any person or entity not a party to the arbitration. Any claim that all or part of this Class Action Waiver is unenforceable, unconscionable, void or voidable may be determined only by a court of competent jurisdiction and not by an arbitrator. The parties understand that any right to litigate in court, to have a judge or jury decide their case or to be a party to a class or representative action is waived, and that any claims must be decided individually, through arbitration.
(i) Waiver of Jury Trial. If for any reason a claim proceeds in court rather than in arbitration, you and Galxe each waive any right to a jury trial.
# Galxe Terms of Use
Source: https://docs.galxe.com/about/legal/terms-of-service
Effective Date: September 10th, 2025
Hello, and welcome to Galxe! These Terms of Use ("Terms") describe your rights and obligations when using the Services (defined below) offered by us or our affiliates.
Please note that these Terms of Use contain Indemnification, Governing Law, Dispute Resolution, Assumption of Risk and Disclaimer of Warranties and Limitation of Liability Sections that affect your rights, including your ability to bring legal claims against us. Please read these Terms, our Privacy Policy and any other terms referenced in this document carefully. If you do not agree to be bound by these Terms, you are not permitted to use our Services.
For Galxe Passport Terms of Use and Privacy Policy, please go here and here, respectively.
# 1. Introduction
Galxe provides a technological platform that empowers brands to build better communities and products in Web3, and is operated by Galxe Group Inc., d/b/a Galxe with registered office at Aegis Chambers, 1st Floor, Ellen Skelton Building, 3076 Sir Francis Drake's Highway, Road Town, Tortola, VG1110, British Virgin Islands ("Galxe", "we", "us", "our"). These Terms govern your access to and use of the Galxe website at [https://www.galxe.com](https://www.galxe.com) ("Website"), our corresponding mobile application ("App") and any other related and connected platforms or services (collectively, the "Services"). By accessing the Services, you agree that you have read, understand, and accept all of the terms and conditions contained in these Terms, including Section 24 ("Dispute Resolution"), as well as the Privacy Policy.
GALXE IS A TECHNOLOGICAL PLATFORM ONLY. WE ARE NOT A BROKER, FINANCIAL INSTITUTION, CREDITOR, BORROWER, AGENT, OR PROVIDE ANY FINANCIAL SERVICES, PRODUCTS OR ADVICE. GALXE IS OFFERED SOLELY AS AN ADMINISTRATIVE PLATFORM. ALL PROGRAMS ARE OFFERED BY THEIR RESPECTIVE ISSUERS ONLY.
# 2. Using Our Services
Important disclaimers. Galxe is not intended as, and does not provide, any investment or financial advice whatsoever. As with any financial or investment decisions, you should conduct your own research and due diligence investigation, to properly evaluate the benefits and risks of any investment or financial transaction. You should also seek the advice and guidance of qualified accountants, financial advisors, tax advisors, legal counsels and investment advisors, in connection with any investment or financial transaction.
Eligibility. To be eligible to use the Services you must be at least 18 years old or of the legal age in the jurisdiction you reside in at the time of using the Services. If you are below the legal age in your jurisdiction, you are prohibited from using the Services.
Updates to Terms of Use. Your use of the Services is subject to your agreement to these Terms, which may be updated by us at any time with or without notice to you. The Effective Date of the most up to date Terms will be provided at the top of each version of these Terms, respectively. Any such updates will be effective upon our publishing such updated Terms. If you do not agree with these Terms, you may not use the Services. If you continue to use the Services following the date of release of an updated set of Terms, you agree to be bound by such updated Terms.
Service Users. By using any of our Services you are a service user ("Service User"). By becoming a Service User, you agree: (a) to provide accurate, current and complete information about yourself; (b) to maintain and promptly update from time to time as necessary your information; (c) to immediately notify us if you discover or otherwise suspect any security breaches related to the Services; (d) that you are fully responsible for all activity on the Services that occurs under your email and password combination, and (e) to comply with all applicable laws in connection with your use of the Services. We may, at any time in our sole discretion, refuse to allow you to become a Service User, or limit the number of User Accounts or Digital Wallets (as defined below) that you may associate with the Services, or suspend or terminate any Service User or User Account, including access to our Services.
You also agree that you will not:
Use the Services under a different wallet address, email address or other identifier if we've disabled access for you under a different wallet address, email address or other identifier, unless you have our written permission first;
Buy, sell, rent or lease access to your Digital Wallet (as defined below) to any third party, unless you have our written permission first; or
Use or access the Services through any unauthorized third party application(s) or client(s), or to disclose or share your User Account information such as your email password, private keys or other sensitive information with any other person.
User Accounts. In order to access certain functions, Service Users may need to connect their Digital Wallet (as defined below). When a Service User connects a Digital Wallet, they create a user account ("User Account") with Galxe. In order to create a User Account, you may be required to provide additional information, such as your name, email address, username, wallet address, and other information as required by Galxe.
Account Communication. By becoming a Service User, you consent to receive electronic communications from Galxe (e.g., via email, push notification, or by posting notices to the Services, etc.). These communications may include notices about your use of the Services (e.g., email changes and/or other transactional information) and are part of your relationship with us. You agree that any notices, agreements, disclosures or other communications that we send to you electronically will satisfy any legal communication requirements, including, but not limited to, that such communications be in writing. You should maintain copies of electronic communications from us by printing a paper copy or saving an electronic copy.
Account Verification and Additional Information. Galxe may require you to provide additional information and documents at the request of any competent authority or in case of application of any applicable law or regulation, including laws related to anti-laundering, sanctions, embargoes, counteracting the financing of terrorism, and other applicable laws. Galxe may also require you to provide additional information and/or documents in cases where it has reason to believe that:
Your use of the Services is related to money laundering or any other illegal or illicit activity;
You have concealed or reported false identification information and/or other details;
Your activities in connection with the Services violated applicable laws;
Such information and/or documents are required to protect the rights of Galxe or those of third parties; or
Transactions effected via your User Account were effected in breach of these Terms.
In such cases, Galxe, in its sole discretion, may pause or cancel your access to any or all Services until such additional information and/or documents are reviewed by us and accepted as satisfying the requirements of applicable law. If you do not provide complete and accurate information and documents in response to such a request, Galxe, in its sole discretion, may refuse to provide the Services to you.
Unless otherwise noted in writing, by submitting personal data through our Site or Services, you agree to the terms of the Privacy Policy and you expressly consent to the collection, use and/or disclosure of your personal data in accordance with the Privacy Policy.
Compliance. The Services are only available to users in certain jurisdictions who can use the Services as permitted under applicable law. You certify that you will comply with all applicable laws (e.g., local, state, federal and other laws) when using the Services. Without limiting the foregoing, by using the Services, you represent and warrant that: (a) you are not located in a country that is subject to sanctions or embargos by the United States, United Kingdom, European Union or United Nations; and (b) you are not listed on any U.S. Government list of prohibited, sanctioned, or restricted parties. In addition, certain Services may not be available to users in certain jurisdictions. You must not use any software or networking techniques, including use of a Virtual Private Network (VPN) to modify your internet protocol address or otherwise circumvent or attempt to circumvent this prohibition. We reserve the right, but have no obligation, to monitor where our Services are accessed from. Furthermore, we reserve the right, at any time, in our sole discretion, to block access to the Services, in whole or in part, from any geographic location, IP addresses and unique device identifiers or to any user who we believe is in breach of these Terms.
Developer Account. If you are using the Services to create a content space, curate user credentials, deploy NFTs, or create user campaigns, you must first apply for a developer account with us ("Developer Account" and each such user, a "Developer"). In order to create a Developer Account you must be of the legal age in the jurisdiction you reside in at the time of using the Services, connect a Digital Wallet, agree to any applicable Developer Account terms and conditions, and take other actions as we may require from time to time.
Galxe OAT. Galxe OAT (on-chain achievement tokens) aims to be a light-weight solution for event organizers and community managers to utilize Galxe's NFT infrastructure and on-chain credential data network to build and distribute NFT badge campaigns easily and reward their community members. To put it simple, Galxe OATs are a digital record of all your life's achievements.
Galxe Compass. From time to time, Galxe Compass collects, based on publicly available third party sources, information (and associated links) regarding current and future airdrops, bounties, rewards and other programs offered by third parties (each such program, a "Third Party Program(s)"). All information provided regarding the Third Party Programs, including the cost, yield, amount of rewards, etc., is based on publicly available information published by their respective third party providers, is provided to you for informational purposes only and cannot be classified or construed as any type of financial, investment or other advice. The ranking or order in which Third Party Programs are displayed is determined by Galxe in its sole discretion and can change from time to time. Unless explicitly disclosed by Galxe, Galxe is not involved in creating, determining, sponsoring, promoting, partnering with, endorsing or otherwise recommending any such Third Party Programs, and does not have the ability to control, direct, modify or otherwise affect the Third Party Programs in any way. Galxe does not verify, screen, vet, or categorize the Third Party Programs listed in any way, and does not guarantee the security, returns, rewards, success or other parameters associated with your participation in such Third Party Programs. You are solely responsible for reviewing, deciding and interpreting whether and to what extent you wish to participate in any such programs. Notwithstanding the foregoing, Galxe reserves the right to remove or delete a Third Party Program at any time, with or without notice for any reason and without liability, in its sole discretion. The inclusion, removal, and/or exclusion of a Third Party Program does not constitute any advice or endorsement of such.
# 3. G Token
Galxe aims to build a permissionless, open, and collaborative credential data network. To this end, Galxe has adopted the G token as an essential component to its ecosystem and infrastructures to functions as the ecosystem's governance token, to incentivizes user participation, and to serve as the primary payment token of the Galxe ecosystem. Here are the utilities of G:
Governance: G can be used for voting & governance in the Galxe Decentralized Autonomous Organization ("DAO"). G token holders shall have the ability to determine various governance parameters, such as controlling the amount of the platform fee collected by the protocol, and determining the appropriate use of funds held by the Galxe Community Treasury.
Paying for Application Module Fee: Developers who aim to utilize Galxe's credential data through Application Modules will be subject to a platform fee ("Platform Fee") which is payable in G.
Paying for Galxe Oracle Engine and Galxe Credential API: Developers pay G to query user credential data through the Galxe Oracle Engine and Galxe Credential API. Currently all query fees are waived during beta testing.
Curating Digital Credentials: Curators can utilize the G token to signal a credential data set's value. Each credential data set will include a revenue stream that will be split between credential stake holders pro-rata.
Galxe Earn: G tokens can be staked by users to unlock additional features, functionalities and rewards on the platform. Users remain responsible for any associated gas or service fees associated with the Galxe Earn program.
# 4. Galxe Rewards Hub
NO PURCHASE IS NECESSARY TO PARTICIPATE IN ANY ACTIVITIES OR EVENTS IN THE GALXE REWARDS HUB. Through interaction with Services, users can earn Galxe Gold (GG). Galxe Gold do not hold any inherent value in real currency, are non-transferable, do not constitute the personal property of the user, nor are they treated as currency or a medium of exchange. GG may not be transferred, and may only be used to participate in the Services. The number of GG earned may vary depending on the nature, type and amount of your interaction with the Services, as determined by us in our sole discretion. We reserve the right to determine, in our sole discretion, the number of GG awarded for any given interaction. We expressly reserve the right, in our sole and absolute discretion, to modify, alter, or change the calculation or valuation of GG at any time and for any reason without prior notice. Such modifications, alterations, or changes may include, but are not limited to, increasing or decreasing the number of GG awarded for a specific interaction, changing the activities for which GG may be awarded, or imposing limits on the accumulation or redemption of GG. We do not guarantee the availability of any particular redemption level or reward. The amount of GG required to redeem any reward or the requirements to be able to access such reward or reward mechanism may be substantially increased, modified, or withdrawn, and restrictions on any reward or its redemption may be imposed at any time. The sale, barter, or other disposal of GG without our express prior written consent, is expressly prohibited.
NO PURCHASE NECESSARY TO ENTER. To enter to receive a Mystery Box without using the Services, mail a handwritten standard sized postcard (no larger than 5" x 7") that legibly provides your first and last name, age, email address, phone number, wallet address capable of receiving the GG required to redeem a Mystery Box, confirmation of which level of Mystery Box you would like to receive, and mailing address ("Alternate Mail Entry Information") to the following address (such mailing, the "Alternate Method of Entry"):
Galxe Rewards Hub Sweepstakes
3 FRASER STREET # 04-23A DUO TOWER, SINGAPORE (189352)
One (1) postcard will result in receipt of one (1) entry. Alternate Method of Entries must be mailed separately. Any Alternate Method of Entry received that is not legible will not be a valid entry. No mass produced typed/copied/printed reproductions of Alternate Method of Entry will be accepted. Proof of submitting an entry will not be deemed by us as proof of receipt or entry. All required information and Alternate Mail Entry Information (collectively, "Entry Information") must be completed in full, be accurate and valid. The Alternate Mail Entry Information must match the information of the entrant that completed the act of physically mailing the postcard. Entrants can enter via both methods/mechanisms described above, however only up to one (1) entry can be received by one (1) entrant using the Alternate Method of Entry, up to once per calendar year. We are not responsible for any wrong, incompatible or incomplete wallet address provided by you via the Alternate Method of Entry. Some countries, regions or geographical including but not limited to the USA, Netherlands, Spain, France, Germany, Belgium, Italy, UAE, Turkey, Australia, Singapore, Japan, India, China may not be eligible to access or use the Galxe Rewards Hub.
# 5. Digital Wallet
Digital Wallet. As part of the Services, you are able to connect your "digital asset wallet" ("Digital Wallet") to your account. You may be required to provide us additional information to connect your Digital Wallet, such as an email address and password. We do not offer our own digital asset wallet and any Digital Wallet that you connect to your User Account is subject to the Terms and Conditions of that service provider (if applicable) and we have do not have any access to, or control over, your connected Digital Wallet.
GALXE DOES NOT CREATE, GENERATE, STORE OR TRANSACT WITH ANY WALLETS. THE CREATION, GENERATION, STORAGE AND TRANSACTING IN DIGITAL WALLETS ARE SOLELY YOUR RESPONSIBILITY. GALXE WILL NEVER ASK YOU FOR, NOR WILL IT EVER RECEIVE A COPY OF, YOUR PRIVATE KEYS. IT IS SOLELY YOUR RESPONSIBILITY TO ENSURE THAT THE DIGITAL WALLET YOU USE IN CONNECTION WITH YOUR ACCOUNT IS SAFE, SECURE AND AUTHORIZED.
# 6. Starboard
Starboard is a data-driven growth intelligence and analytics platform operated within the Galxe ecosystem designed to facilitate the identification, engagement, and rewarding of impactful contributors through the measurement of both offchain and onchain activities. Your use of Starboard constitutes your acknowledgment that such participation is expressly subject to the complete guidelines, rules, and terms established by Galxe (including these Terms, Privacy Policy, and any Campaign-Specific Rules). While the platform endeavors to provide accurate and reliable functionality and insights (including but not limited to Aura Index scores, AI Sentiment analysis, contributor leaderboards, TVL monitoring, transaction tracking, and NFT/wallet analytics), Galxe (including its affiliates, shareholders, directors, officers, employees, contractors, agents, and successors) HEREBY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, ACCURACY, COMPLETENESS, TIMELINESS, AND CONTINUOUS/ERROR-FREE OPERATION OR DATA FEEDS. Galxe expressly disclaims responsibility for:
(i) Any third-party campaigns, rewards, reward pools, smart contracts, partner projects, or content accessed via Starboard;
(ii) The accuracy, completeness, outcome, or utility of any analytics, metrics (including Aura Index, AI Sentiment, contributor rankings), insights, or credentials generated or displayed;
(iii) Loss of funds, data, access, rewards, or assets due to technical failure, hacking, network congestion, blockchain forks, data source errors, user error, or inaccuracies in algorithmic calculations;
(iv) User compliance with applicable laws (including AML/KYC) or project rules;
(v) The performance, value, or outcome of any rewards distributed through Starboard or associated campaigns;
(vi) The ranking, qualification, or eligibility of any user appearing on leaderboards or receiving rewards;
(vii) Any decisions made or actions taken based on Starboard data or analytics.
You agree that your use of Starboard and any reliance on its data, analytics, or leaderboards is at your sole risk and expense. You expressly waive any and all claims (including for consequential, incidental, or punitive damages) against Galxe Entities arising out of or related to your use, misuse, interpretation of data, participation in campaigns, leaderboard rankings, receipt or non-receipt of rewards, or reliance on Starboard's outputs. Galxe does not endorse any third-party projects, campaigns, or rewards advertised or facilitated through Starboard. Galxe reserves the right to modify, suspend, or terminate Starboard, its features, algorithms, leaderboards, or your access at any time without notice or liability.
# 7. Galxe Business+
Galxe Business+ is a premium enterprise subscription service (Growth, Pro, Enterprise tiers) providing business-exclusive benefits including but not limited to: API access with tier-specific rate limits, Sybil prevention tools, gas credit subsidies, GG reward multipliers, Space verification checkmarks, leaderboard analytics, and priority support channels. By subscribing, Client irrevocably agrees: (i) All fees (including quarterly/annual payments) are non-refundable and subject to the campaign rules and invoice specifications provided at purchasel; (ii) Benefits including gas credits expire monthly and are non-transferable; (iii) Upgrades trigger immediate benefit recalculation with prorated term extensions while downgrades are expressly prohibited during active terms; (iv) "Unlimited" API/Starboard access denotes Galxe-imposed thresholds only and excludes third-party limitations. Galxe (including affiliates, directors, agents) DISCLAIMS ALL WARRANTIES: benefit functionality, Sybil prevention efficacy, or data accuracy. No liability for: (a) Client losses from service interruptions or API failures; (b) Tax implications of subsidies/multipliers; (c) Third party processing errors; or (d) Bot analysis false positives. Premium support denotes prioritized response only—no resolution guarantees. All benefits except grace-period extensions terminate immediately upon subscription lapse.
# 8. Galxe+
Galxe+ constitutes a paid subscription service (tiers: Mini, Premium, Unlimited) offering tier-specific benefits including but not limited to: transaction fee credits, Galxe Gold reward multipliers, third-party partner integrations and limited-time fee waivers for Galxe Passport/Score. By subscribing, User irrevocably acknowledges and agrees: (i) All fees are non-refundable and subscriptions automatically renew for successive billing cycles until canceled ≥24 hours prior to renewal; (ii) Benefits are subject to monthly expiration, network availability, and third-party partner terms; (iii) "Unlimited" designates the absence of Galxe-imposed limits only and expressly excludes constraints arising from blockchain network conditions (including gas fee volatility), third-party service interruptions, or User failure to maintain adequate Smart Savings balances; (iv) Downgrades require active subscription expiration. Galxe and its affiliates expressly disclaim all warranties, whether express or implied, including fitness for purpose, benefit continuity, or accuracy of credit allocations. Galxe Entities shall bear no liability for: (a) tax consequences of benefits received; (b) expired or misallocated credits; (c) modifications to partner offerings; (d) Smart Savings operational failures; or (e) User eligibility for regionally restricted services. All benefits terminate upon subscription cancellation
# 9. Quest
Galxe Quest is a no-code campaign management platform operated within the Galxe ecosystem that enables projects to create customizable reward-based loyalty programs for user acquisition, engagement, and retention. Your use of Galxe Quest constitutes acknowledgment that participation is expressly governed by Galxe's Terms, Privacy Policy, Campaign-Specific Rules, Galxe Passport terms, and third-party platform policies (e.g., Twitter, Discord, Snapshot). While Quest aims to provide functionality for tracking onchain/offchain metrics (e.g., Twitter engagement, Discord roles, GitHub contributions, DAO votes), Galxe (including affiliates, shareholders, directors, officers, employees, contractors, agents, and successors) HEREBY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING MERCHANTABILITY, FITNESS FOR PURPOSE, NON-INFRINGEMENT, SECURITY, DATA ACCURACY, OR UNINTERRUPTED OPERATION OF INTEGRATED THIRD-PARTY SERVICES (E.G., APIS, GOOGLE SHEETS, SNAPSHOT). Galxe expressly disclaims responsibility for:
(i) Third-party Quests, rewards, smart contracts, or project claims;
(ii) Accuracy of Quest completion tracking, credential issuance, BYOD ("Bring Your Own Data") integrations, or Sybil prevention credentials;
(iii) Loss of funds, data, rewards, or assets due to hacking, third-party API failures, ZK technology vulnerabilities, blockchain failure, or user error;
(iv) User compliance with laws (data protection regulations, tax, AML) or third-party campaign rules;
(v) Value, functionality, or redemption of rewards;
(vi) Actions of campaign creators/participants (e.g., fraudulent data submissions via CSV/API);
(vii) Functionality of integrated platforms (e.g., Discord bot, Twitter API);
(viii) Storage/security of user data in "off-chain vaults" or Galxe Passport controls;
(ix) Custom Quest templates or configurations created via no-code tools.
You agree use of Quest is at your sole risk and expense. You waive all claims against Galxe Entities arising from:
(a) Quest participation, data integration errors, or credential validity;
(b) Reliance on analytics, Sybil resistance, or "loyal user" identification;
(c) Misuse of Galxe Passport, revoked data access, or ZK technology limitations;
(d) Geo-fenced/QR code event tracking inaccuracies;
(e) BYOD data corruption or compliance violations.
Galxe does not guarantee data encryption standards, absolute Sybil resistance, or universal identity portability. Campaign creators are solely liable for BYOD data legality and third-party integrations. Galxe reserves the right to suspend Quests, APIs, or user access without notice.
# 10. Earndrop
Galxe Earndrop is a meritocratic token distribution service operated within the Galxe ecosystem that enables projects to reward targeted users (e.g., past contributors, community members) with tokens based on predefined eligibility criteria. Your participation in any Earndrop constitutes acknowledgment that:
(i) Tokens distributed have no guaranteed value, utility, or future performance;
(ii) Eligibility determinations (including algorithmic scoring) are final and non-appealable;
(iii) Claims may incur gas fees/network charges controlled by blockchain protocols, not Galxe.
Galxe (including affiliates, shareholders, directors, officers, employees, contractors, agents, and successors) HEREBY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING MERCHANTABILITY, FITNESS FOR PURPOSE, NON-INFRINGEMENT, OR ACCURACY OF ELIGIBILITY CALCULATIONS. Galxe expressly disclaims responsibility for:
(a) Token value fluctuations, liquidity, or delistings;
(b) Tax implications (including reporting obligations) of received tokens;
(c) Project decisions to modify/cancel Earndrops or eligibility rules;
(d) Losses from hacking, wallet compromise, or failed transactions during claims;
(e) Regulatory actions classifying tokens as securities in your jurisdiction.
You agree that:
Participation is not an investment solicitation and tokens confer no ownership rights;
You alone bear responsibility for tax compliance, wallet security, and regulatory research;
Earndrop eligibility does not imply future rights, allocations, or project endorsement.
You waive all claims (including consequential/punitive damages) against Galxe Entities arising from Earndrop participation, token receipt, or eligibility disputes. Galxe does not custody tokens or control project distributions. Unclaimed tokens may be forfeited per project terms
# 9. User Conduct
Prohibited Uses. You may not use the Services to engage in the following categories of activity ("Prohibited Uses"). The specific types of use listed below are representative, but not exhaustive, and Galxe reserves the right to update or amend such list in its sole discretion at any time, with or without notice to you. These Prohibited Uses are in addition to the Community Guidelines (discussed below). If you are uncertain as to whether or not your use of the Services involves a Prohibited Use or have questions about how these requirements apply to you, please contact us at [support@galxe.com](mailto:support@galxe.com). By becoming a Service User, you agree that you will not use the Services to do or undertake any of the following, as determined by Galxe in its sole discretion:
Abusive Activity: Actions which: (i) impose an unreasonable or disproportionately large load on our infrastructure, or detrimentally interfere with, intercept, or expropriate any system, data, or information; (ii) transmit or upload any material to the Services that contains viruses, trojan horses, worms or any other harmful or deleterious programs; (iii) attempt to gain unauthorized access to the Services, other Digital Wallets not belonging to you, computer systems or networks connected to the Services, through password mining or any other means; (iv) use the account of any third party to access or use the Services, except in the case of applications which are specifically authorized by a third party to access such third party's Digital Wallet and information; or (v) transfer your access or rights to use the Services to a third party, unless by operation of law or with the express permission of Galxe.
Unlawful Activity: Activity which would violate, or assist in violation of, any law, statute, ordinance or regulation, sanctions programs administered in any of the countries where Galxe conducts business, including but not limited to the U.S. Department of Treasury's Office of Foreign Assets Control ("OFAC"), or which would involve proceeds of any unlawful activity.
Abuse Other Users: Interfere with another individual's access to or use of the Services; defame, abuse, extort, harass, stalk, threaten or otherwise violate or infringe the legal or other rights (such as, but not limited to, rights of privacy, publicity and intellectual property) of others; or harvest or otherwise collect information from the Services about others, including without limitation email addresses and/or public or private Digital Wallet keys, without proper consent.
Fraud: Activity which operates to defraud Galxe, any Galxe user(s) or any other person, or provide any false, inaccurate or misleading information to Galxe.
Copyright violations: Activity which intentionally infringes upon another's copyright, or other intellectual rights, protections, including unauthorized copying or performing of copyrighted works available on the Services.
Misleading statements on investments: Activity that promotes, markets, or in any other way communicates the message of, NFTs on Galxe being an investment, such as making statements regarding the expectation that the monetary value of NFTs will increase in time.
Your legal obligations. It is possible that your use of the Services may result in certain reporting, tax or other legal obligations on your part. For example, certain jurisdictions require their residents to report international money or cryptocurrency transfers that exceed certain amounts. You agree and understand that we do not provide legal, tax, or investment advice. You agree to seek your own advice as necessary, and to comply with any legal obligations you may have in connection with your use of our Services.
# 10. Subscriptions
Certain Services (the "Premium Services") require payment of a fee for use of such Premium Service and you agree to pay such fees if you wish to utilize any such Premium Service. The Company may add new Services for additional fees and charge and/or add or amend fees and charges for existing Services, including Premium Services, at any time in our sole discretion. Any change to the pricing and payment terms shall become effective immediately, unless we state otherwise. When you purchase a subscription for the Services ("Subscription"), you expressly authorize us to charge you for such Subscription. Payment may be made in USDT, USDC or other forms of digital assets that we may accept from time to time. The applicable United States dollar equivalent of digital assets shall be determined by us in our sole discretion.
If you purchase a Subscription, you will be charged the Subscription fee, plus any applicable taxes and other charges (collectively, the "Subscription Fee"), at the beginning of your Subscription. At the end of the subscription period ("Subscription Period"), you may lose access to the Premium Services unless you renew your Subscription at the then-current Subscription Fee. Your Subscription continues for the Subscription Period until cancelled by you or we terminate your access to or use of the Services or Subscription in accordance with these Terms.
You may cancel your Subscription at any time; however, there are no refunds for cancellation. In the event that we suspend or terminate your Subscription, you understand and agree that you shall receive no refund or exchange for any unused time on a Subscription, any license or Subscription Fees for any portion of the Services, any content or data associated with your Subscription, or for anything else.
We or certain third-party service providers may offer free trials to a particular Service.
# 11. Non-Fungible Tokens
NFT Acquisition. Users may have the ability to obtain one or more non-fungible tokens ("NFT") on the Services. An NFT is a record on the distributed public ledger known as the blockchain. Our Service permits users with a User Account to mint NFTs . Users can then offer those NFTs minted on our Service for sale, distribution, as rewards or other forms of incentives to other users. You are solely responsible for conducting research on an NFT, as well as understanding the seller's terms and conditions of the potential purchase or sale of the NFT (the "Purchase Terms"), prior to purchase or sale. We do not endorse any NFT or make any claims regarding, authenticity, ownership, uniqueness, intellectual property, licenses, scarcity, rarity, value, functionality and/or other attributes or rights thereto. In order to acquire a NFT on our Services, you will need to have a User Account. To complete your transaction and acquire the NFT, you will need to have the required amount of tokens and any applicable gas or transaction fees in your Digital Wallet. When you complete the transaction, it will be recorded on the blockchain and the NFT will be transferred to your Digital Wallet ("NFT Transaction"). Galxe does not claim ownership to any content accessible through the Services and does not endorse any Developer. Galxe operates as a platform connecting users and Developers by minting NFTs for Developers and allowing users to purchase the NFTs. Developers decide the attributes of the NFTs you purchase. Users acknowledge and agree that the NFTs minted and purchased on Galxe are not intended for the purpose of investment or speculation. Users who hold NFTs that are minted and/or purchased on Galxe do not and are not entitled to receive any income or monetary payouts in any form by virtue of their ownership of the NFT.
Galxe Fee. Each NFT Transaction is conducted using digital assets in your Digital Wallet. When a Developer lists its NFTs for the initial sale of the Services ("Initial Offering"), the Developer will set the price in digital assets for the NFT Content (as defined below). A fee of 8% of the revenue from the Initial Offering is deducted from the Initial Offering revenues and transferred to Galxe.
Gas Fees. Creating, buying, selling or transferring NFTs may be subject to fees, commissions, royalties and other charges ("Fees") established from time to time in the sole discretion of Galxe, Developer, and/or participants in the blockchain ecosystem, including an Artist Royalty Fee (as defined below). On the date of initial publication of these Terms, Fees include service fees established by and payable to Galxe and "gas" (fees paid to miners through users' Digital Wallet as consideration for mining the NFT Transactions). Service fees may be adjusted from time to time in the sole discretion of Galxe.
# 12. TERMS APPLICABLE TO DEVELOPERS
If you are using the Services as a Developer to mint or sell NFTs, you agree to the following additional terms and conditions:
· Royalties. in each sale by other sellers following the Initial Offering, you may receive the percentage of revenue with respect to each such sale set forth in the applicable field of the NFT at the time of creation ("Artist Royalty Fee").
· NFT Content. As between us and you, you shall continue to exclusively own all right, title and interest in and to the digital art embodied in the NFTs and any name, likeness, image, signature, voice and other identifiable characteristics included in the digital art embodied in the NFTs, creative assets you provide to us, and your name, logos and trademarks, and all intellectual property rights in the foregoing (collectively, the "NFT Content"). Notwithstanding the foregoing, you grant to us a perpetual, irrevocable, worldwide, non-exclusive, royalty-free, fully paid-up, license, with the right to sublicense through multiple tiers, to use NFT Content for the purpose of performing our obligations under these Terms, including hosting the NFT Content and marketing and facilitating the sale of the NFTs, and marketing or promoting the Services.
· Creator Obligations and Perks. You shall obtain all rights to the NFT Content in connection with the use thereof by Galxe as contemplated in these Terms, and the awarding and administration of the benefits that you sell or list in connection with the sale of your NFT, as applicable, including, but not limited to: (i) clearing and obtaining any rights in connection with the NFT Content, including any music performance rights and payment of royalties to any performing rights organizations; (ii) acquiring any services or materials needed in connection with the NFTs and benefits offered to purchasers; and (iii) the costs and compliance for the benefits, including as specified in the Purchase Terms.
· Promotions Tool. Our Services may enable you to administer a promotion (e.g., a contest or sweepstakes) (a "Promotion") through the use of a promotions tool (the "Promotions Tool"). By using the Promotions Tool, you (a) agree to fully release us from any liability in connection with the promotion, and (b) acknowledge and agree that a Promotion is not in any way sponsored, endorsed, or administered by us.
o Administration of Promotion. If you use the Promotions Tool to administer a promotion, you are responsible for the lawful operation of that promotion, including: (i) the official rules; (ii) offer terms and eligibility requirements (e.g., age and residency restrictions); and (iii) compliance with applicable rules (e.g. terms and conditions of any platform on which a Promotion may be advertised, restrictions on any prizes, etc.) and regulations governing the Promotion and all prizes offered (e.g., registration, bonding, and obtaining necessary regulatory approvals). You further represent and warrant that the Promotion administered through the Promotion Tools will be conducted in compliance with all applicable laws, rules, and regulations.
o Required Content. In using the Promotion Tool to administer a Promotion, you represent and warrant that you will provide official rules to the participants of such Promotions, and you further represent and warrant that the official rules for any such Promotion administered through the Promotion Tool will include the following provisions:
This promotion is not sponsored by Galxe Group Inc.., d/b/a Galxe ("Galxe"). You acknowledge and agree that Galxe is not responsible for the administration or fulfilment of this promotion. By participating in this promotion, you hereby absolutely, unconditionally, and irrevocably covenant not sue (at law, in equity, through private arbitration, or through any regulatory proceeding or otherwise) Galxe in connection with this promotion. If you violate the foregoing covenant, you agree to pay, in addition to such other damages as a result of such violation, all attorneys' fees and costs (which is to be interpreted broadly to include all out-of-pocket obligations incurred by Galxe in defending such action) incurred by Galxe as a result of such violation.
o No Assistance. Galxe will not assist you in the administration of your Promotion, and you agree that if you use the Promotions Tool to administer your Promotion, you do so at your own risk.
· Warranties. You represent and warrant that (i) you have the full right, power and authority to grant the rights granted or agreed to be granted hereunder, including, but not limited to, fully cleared permissions, consents, rights and licenses to the NFT Content in these Terms; (ii) the NFT Content, the NFTs, and the listing and sale contemplated by these Terms, complies with all, and do not and will not violate any applicable law, statute, rule, or regulation, will perform in accordance with the intended specifications and without material error, and will be delivered free and clear of any claims, liens or rights of third parties; (iii) the NFT Content and Galxe's use thereof in accordance with these Terms does not and will not infringe any intellectual property rights of any third party or any right of privacy or publicity, or contain any libelous, defamatory, obscene or unlawful material, or otherwise violate or infringe any other right of any third party; (iv) you will fulfill your obligations under any terms with a Purchaser of the NFTs, as applicable; (v) any advertising or promotion of the NFTs by you or on your behalf will not constitute false, deceptive or unfair advertising or disparagement under any applicable laws and will not suggest a likely increase in value of the NFTs; and (vi) you will not use the proceeds retained from sales of the NFT, whether through the Services or any other platform for capital raising purposes.
# 13. Smart Balance
By utilizing Smart Balance, you agree to the following additional terms and conditions:
Non-Withdrawable: Smart Balance funds or credits cannot be withdrawn. They must be exclusively used for designated services provided on Galxe.com.
Exclusive Use: Smart Balance is only valid on Galxe.com and has no value, usability, or transferability outside the platform.
Currency Denomination: All Smart Balance amounts are denominated in U.S. dollars. When deposits are made in other currencies, the final credited amount will be determined based on the applicable exchange rate at the time of the transaction.
Service Fees: The use of Smart Balance is subject to service fees. Fees may vary depending on the type of deposit and will be calculated based on the associated gas fee. Minimum fees may apply—please contact us for detailed fees.
# 14. Chatbot
Our Services may include, from time to time, an automated chat box ("Chatbot") to assist users in their use of the Services. The Chatbot provides information about various topics that are found and generated via user input and the underlying algorithm.
By using the Chatbot, you agree and acknowledge that we cannot and do not guarantee the accuracy of the information provided, and that Galxe assumes no responsibility whatsoever or guarantee the timeliness, accuracy or completeness of the information provided. The Chatbot may contain links to third-party websites. These links are provided for your convenience and do not constitute an endorsement or approval by Galxe of any third-party content. We are not responsible for the content or privacy practices of these external sites.
# 15. GALXE SCORE
As part of the Services, you are able to purchase a Subscription for a "Web3 Score" (the "Web3 Score"). The Web3 Score is for entertainment purposes only and is not, and does not purport to be, an accurate depiction of any Service User's financial activity nor does it serve as an accreditation of any kind. To obtain your Web3 Score, you are required to pay a Subscription Fee (the "Subscription Fee"). You may be required to provide us, and we may collect via your linked social media channels or analysis of on-chain wallet activities, additional information to create your Web3 Score, including information required to confirm your identity ("Identifying Information"). By purchasing a Subscription for the Web3 Score, you agree that we may share your information, including any Identifying Information, with certain third parties, including third-party developers who integrate with our application programming interface.
# 15. Access to our Services
Suspension, Termination, and Cancellation. Galxe may, at its option and in its sole discretion: (a) suspend or restrict your User Account or Developer Account and/or access to any or all of the Services, and/or (b) deactivate or cancel your User Account or Developer Account and block your access to the Services, if: (i) we are so required by a facially valid subpoena, court order, or binding order of any government authority; (ii) we reasonably suspect you of using the Services in connection with a Prohibited Uses; (iii) your use of the Services is subject to any pending litigation, investigation or government proceeding and/or we, in our sole discretion, perceive a heightened risk of legal or regulatory non-compliance associated with your activity; (iv) any of our service partners are unable to support your use thereof; (v) you take any action that Galxe deems in its sole discretion as circumventing Galxe's controls, or abusing promotions which Galxe may offer from time to time; or (vi) you breach these Terms.
Notice to You. If Galxe suspends or closes your account or terminates your use of the Services for any reason, we will provide you with notice of our actions, unless a court order or other legal process prevents or prohibits Galxe from providing you with such notice. You acknowledge that Galxe's decision to take certain actions, including limiting access to, suspending, or disassociating your Digital Wallet from the Services, may be based on confidential criteria that are essential to Galxe's risk management and/or security protocols. You agree that Galxe is under no obligation to disclose the details of its risk management and/or security procedures to you.
Access to NFTs. Your NFTs are stored in your Digital Wallet and we do not have access or control over your Digital Wallet. In the event our Services are no longer available to you, the NFTs you have purchased are in your Digital Wallet.
# 16. Copyright and License to You
Information Ownership. Unless otherwise indicated in writing by us, the Services and all content and other materials contained therein, including, without limitation, the Galxe logo and all designs, text, graphics, pictures, information, data, software, sound files and/or other files related thereto and/or associated therewith and the selection and arrangement thereof (collectively, "Content") are and shall remain the sole and proprietary property of Galxe and/or our affiliates or licensors, including the Developers, if and as applicable.
If you print, copy, modify, download or otherwise use or provide any other person with access to any part of the Services in breach of these Terms, your right to use the Services will terminate immediately and you must, at our option, either return or destroy any Content you have copied, downloaded , or otherwise obtained from the Services. No right, title or interest in or to the Services or any Content thereon is or shall be transferred to you, and all rights not expressly granted herein are reserved by Galxe and/or its affiliates. Any use of the Services not expressly permitted by these Terms shall be deemed a material breach of these Terms and may violate copyright, trademark and/or other laws.
NFT Ownership. If you purchase, receive as rewards, or otherwise acquire a NFT via our Services, you may obtain access or a license to certain content associated with that NFT ("NFT Content").
All NFT Content is owned by the applicable Developers, as applicable. By hosting, minting, and otherwise offering NFT Content, Galxe warrants that we have a license to host and offer said NFT Content. Galxe makes no other warranties regarding the NFT Content.
NFT Content License to You. By purchasing a NFT, you are granted a limited, exclusive right to access, view, stream, download, playback, or otherwise access ("NFT Content License") the NFT Content associated with the NFT you purchase for personal consumption only, unless otherwise explicitly authorized by the applicable Developers' terms of services. The NFT Content License is subject to these Terms, and/or any additional terms as may be presented to you at the time you purchase the NFT or first access the NFT Content.
Third Party Intellectual Property. Notwithstanding anything to the contrary in these Terms, the Services and Content may include software components provided by Galxe or its affiliates or a third party that are subject to separate license terms, in which case those license terms will govern the usage of such software components, as applicable.
Limited License to You. These Terms grant users a limited and non-exclusive right to use the Services, including all Content thereon. Except as indicated otherwise herein or in any additional terms or conditions, you may not reproduce, distribute, modify, create derivative works of, publicly display, publicly perform, republish, download, store, transmit or otherwise exploit any of the Content on our Services, except as follows:
Your device may temporarily store copies of such materials in RAM incidental to your accessing and viewing those materials.
You may store files that are automatically cached by your web browser for display enhancement purposes.
If we provide any so-called "social media" features as part of the Services, you may take such actions as are enabled by such features and are consistent with these Terms.
You must not:
Modify copies of any Content from the Services.
Use any illustrations, photographs, video or audio sequences or any graphics available through the Services separately from the accompanying text.
Delete or alter any copyright, trademark or other proprietary rights notices from copies of materials available through the Services.
If you wish to make any use of Content other than that set out in this Section, please address your request to: [support@galxe.com](mailto:support@galxe.com).
Third Party Services. The Services may contain links to third-party websites ("Third-Party Websites") and/or applications ("Third-Party Applications"). When you click on a link to a Third-Party Website or Third-Party Application, we will not warn you that you have left the Services and are subject to the terms and conditions (including privacy policies, if and as applicable) of another website or destination. Such Third-Party Websites and Third-Party Applications are not under the control of Galxe. Galxe is not responsible for any Third-Party Websites or Third-Party Applications and shall not be liable with respect to any use thereof. Galxe provides these Third-Party Websites and Third-Party Applications only as a convenience and does not review, approve, monitor, endorse, warrant or make any representations with respect to Third-Party Websites or Third-Party Applications or their products or services. You use all links in Third-Party Websites, and Third-Party Applications at your own risk. When you leave our Services, these Terms and any of our other policies no longer govern. You should review all applicable agreements and policies, including privacy and data gathering practices, of any Third-Party Websites or Third-Party Applications, and should make whatever investigation you feel necessary or appropriate before proceeding with any transaction with any third party.
Links to our Services. You are granted a limited, nonexclusive, nontransferable right to create a text hyperlink to the Services for noncommercial purposes, provided that such link does not portray Galxe or our affiliates or any of our products or services in a false, misleading, derogatory or otherwise defamatory manner, and does not imply that Galxe is affiliated with or supports or endorses any product or service, and provided further that the linking site does not contain any adult or illegal material or any material that may be deemed, in Galxe's sole discretion, offensive, harassing or otherwise objectionable. This limited right may be revoked or modified by us at any time, for any reason. You may not use a logo or other proprietary graphic or intellectual property of Galxe to link to the Services or Content without our express written permission. Further, you may not use, frame or utilize framing techniques to enclose any Galxe trademark, logo or other proprietary information, including the images found on the Services, the content of any text or the layout or design of any page, or form contained on a page, on the Services without our express written permission.
Trademark. The Galxe logo and any Galxe product or service names, logos or slogans that may appear on the Services are trademarks of Galxe or our affiliates and may not be copied, imitated or used, in whole or in part, without our prior express written permission. You may not use any so-called "metatags" or other "hidden text" utilizing "Galxe" or any other name, trademark or product or service name of Galxe or our affiliates without our prior written permission. In addition, the look and feel of the Services and Content, including, without limitation, all page headers, custom graphics, button icons and scripts, constitute the service mark, trademark or trade dress of Galxe and/or its affiliates, and may not be copied, imitated or used, in whole or in part, without our prior written permission. All other trademarks, registered trademarks, product names and Galxe names or logos mentioned on the Services are the property of their respective owners and may not be copied, imitated or used, in whole or in part, without the permission of the applicable trademark holder. Reference to any products, services, processes or other information by name, trademark, manufacturer, supplier or otherwise does not constitute or imply endorsement, sponsorship or recommendation by Galxe.
# 17. DMCA Notice and Procedure for Copyright Infringement Claims
As Galxe asks others to respect its intellectual property rights, it respects the intellectual property rights of others. Galxe, in appropriate circumstances, may remove from the Services information that might infringe the intellectual property rights of others.
## 1) Procedure for Reporting Copyright Infringements
If you believe your work has been used or copied in a way that constitutes copyright infringement and such infringement is occurring on the Galxe Services, you may submit a notification pursuant to the Digital Millennium Copyright Act ("DMCA") by providing our Designated Agent with the following information in writing (see 17 U.S.C 512(c)(3) for further detail):
An electronic or physical signature of the person authorized to act on behalf of the owner of the copyright's interest;
A description of the copyrighted work that you claim has been infringed, including the URL (i.e., web page address) of the location where the copyrighted work exists or a copy of the copyrighted work;
Identification of the URL or other specific location on the Galxe Services where the material that you claim is infringing is located; your address, telephone number, and E-mail address;
A statement by you that you have a good faith belief that the disputed use is not authorized by the copyright owner, its agent, or the law; and
A statement by you, made under penalty of perjury, that the above information in your notice is accurate and that you are the copyright owner or authorized to act on the copyright owner's behalf.
You acknowledge that if you fail to comply with all of the requirements of this section, your DMCA notice may not be valid and we will have no obligation to respond or acknowledge receipt of your notice. Please note that you will be liable for damages (including costs and attorneys' fees) if you misrepresent or make bad faith claims that any material on the Galxe Services infringes your copyrights. You can contact our Designated Agent via e-mail at [dmca@galxe.com](mailto:dmca@galxe.com).
THE DESIGNATED AGENT SHOULD BE CONTACTED ONLY IF YOU BELIEVE THAT YOUR WORK HAS BEEN USED OR COPIED IN A WAY THAT CONSTITUTES COPYRIGHT INFRINGEMENT AND SUCH INFRINGEMENT IS OCCURRING ON THE GALXE SERVICES. ALL OTHER INQUIRIES DIRECTED TO THE DESIGNATED AGENT WILL NOT RECEIVE A RESPONSE.
## 2) Receipt of Proper Infringement Notification
Once a proper bona fide infringement notification has been received by the Designated Agent, it is Galxe's policy:
To remove or disable access to the infringing content;
To notify the content provider, member, or user ("Content Provider") that it has removed or disabled access to the content; and
That repeat offenders will have the infringing content removed from the system and that Galxe may terminate such Content Provider's access to the Galxe Services.
## 3) Procedure to Supply a Counter-Notice to the Designated Agent
If the Content Provider believes that the content that was removed or to which access was disabled is either not infringing or the Content Provider believes that it has the right to post and use such content, the Content Provider may send the Designated Agent a counter-notice, which must contain the following:
Content Provider's contact information, including full legal name (not that of a company) of the submitter, an email address, a physical address, and a phone number.
The location, including any URL, of the content that has been removed or disabled.
The following statement, to which Content Provider must agree: "I consent to the jurisdiction of the Federal District Court for the district in which my address is located, or if my address is outside of the United States, the judicial district in which Galxe is located, and will accept service of process from the claimant."
The following statement: "I swear, under penalty of perjury, that I have a good faith belief that the material was removed or disabled as a result of a mistake or misidentification of the material to be removed or disabled."
A physical or electronic signature. To satisfy this requirement, Content Provider may type the submitter's full legal name (not that of a company) at the bottom of your electronic counter-notification.
If a counter-notice is received by the Designated Agent, Galxe may send a copy of the counter-notice to the original complaining party informing that person that it may replace the removed content or cease disabling it in ten business days.
If Galxe does not receive notice within ten business days that the original complaining party is seeking a court order to prevent further infringement of the content, we may replace or cease disabling access to the material that was removed. The decision to replace or cease disabling access to any content is at Galxe's sole discretion.
# 18. Indemnification
To the fullest extent permitted by applicable law, you agree to indemnify, defend and hold harmless Galxe, and our respective past, present and future employees, officers, directors, contractors, consultants, equity holders, suppliers, Creators, vendors, service providers, parent companies, subsidiaries, affiliates, agents, representatives, predecessors, successors and assigns (individually and collectively, the "Galxe Parties"), from and against all actual or alleged claims, damages, awards, judgments, losses, liabilities, obligations, penalties, interest, fees, expenses (including, without limitation, attorneys' fees and expenses) and costs (including, without limitation, court costs, costs of settlement and costs of pursuing indemnification and insurance), of every kind and nature whatsoever, whether known or unknown, foreseen or unforeseen, matured or unmatured, suspected or unsuspected, in law or equity, whether in tort, contract or otherwise (collectively, "Claims"), including, but not limited to, damages to property or personal injury, that are caused by, arise out of or are related to (a) your use or misuse of the Services, (b) any Feedback (as defined below) you provide, (c) your violation of these Terms or applicable laws, and/or (d) your violation of any right(s) of any third party. You agree to promptly notify Galxe of any Claim(s) and shall cooperate fully with the Galxe Parties in defending such Claims. You further agree that the Galxe Parties shall have control of the defense or settlement of any third party Claims. THIS INDEMNITY IS IN ADDITION TO, AND NOT IN LIEU OF, ANY OTHER INDEMNITIES SET FORTH IN ANY WRITTEN AGREEMENT(S) BETWEEN YOU AND GALXE.
# 19. Feedback
We appreciate feedback, comments, ideas, proposals and suggestions for improvements to the Services ("Feedback"). If you choose to submit Feedback, you agree that we are free to use it without any restriction or compensation to you.
# 20. Disclaimers
EXCEPT AS EXPRESSLY PROVIDED TO THE CONTRARY IN A WRITING BY GALXE, THE SERVICES, CONTENT CONTAINED THEREIN, AND ANY DIGITAL ASSET(S) LISTED THEREIN ARE PROVIDED ON AN "AS IS" AND "AS AVAILABLE" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. GALXE (AND ITS AFFILIATE(S), LICENSOR(S) AND/OR OTHER BUSINESS ASSOCIATE(S)) MAKE NO WARRANTY THAT THE SERVICES: (A) WILL MEET YOUR REQUIREMENTS; (B) WILL BE AVAILABLE ON AN UNINTERRUPTED, TIMELY, SECURE OR ERROR-FREE BASIS; OR (C) WILL BE ACCURATE, RELIABLE, COMPLETE, LEGAL OR SAFE. GALXE DISCLAIMS ALL OTHER WARRANTIES OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT AS TO THE SERVICES OR CONTENT CONTAINED THEREIN. GALXE DOES NOT REPRESENT OR WARRANT THAT CONTENT ON THE SERVICES IS ACCURATE, COMPLETE, RELIABLE, CURRENT OR ERROR-FREE. WE WILL NOT BE LIABLE FOR ANY LOSS OF ANY KIND FROM ANY ACTION TAKEN IN RELIANCE ON MATERIAL OR INFORMATION CONTAINED ON THE SERVICES. WHILE GALXE ATTEMPTS TO MAKE YOUR ACCESS TO AND USE OF THE SERVICES AND CONTENT SAFE, GALXE CANNOT AND DOES NOT REPRESENT OR WARRANT THAT THE SERVICES, CONTENT OR OUR SERVERS IS/ARE FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS. WE CANNOT GUARANTEE THE SECURITY OF ANY DATA THAT YOU DISCLOSE ONLINE. YOU ACCEPT THE INHERENT SECURITY RISKS OF PROVIDING INFORMATION AND DEALING ONLINE OVER THE INTERNET AND WILL NOT HOLD US RESPONSIBLE FOR ANY BREACH OF SECURITY UNLESS IT IS DUE TO OUR GROSS NEGLIGENCE.
WE WILL NOT BE RESPONSIBLE OR LIABLE TO YOU FOR ANY LOSS AND TAKE NO RESPONSIBILITY FOR, AND WILL NOT BE LIABLE TO YOU FOR, ANY USE OF ANY DIGITAL ASSETS OR NFT CONTENT, WHETHER IN CONNECTION WITH YOUR DIGITAL WALLET OR OTHERWISE, INCLUDING BUT NOT LIMITED TO ANY LOSSES, DAMAGES OR CLAIMS ARISING FROM: (A) USER ERROR, SUCH AS FORGOTTEN PASSWORDS, PRIVATE KEYS OR SEED PHRASES, INCORRECTLY CONSTRUCTED TRANSACTIONS OR MISTYPED ADDRESSES; (B) SERVER FAILURE OR DATA LOSS; (C) CORRUPTED WALLET FILES; (D) UNAUTHORIZED ACCESS TO APPLICATIONS; (E) ANY UNAUTHORIZED THIRD PARTY ACTIVITIES, INCLUDING WITHOUT LIMITATION THE USE OF VIRUSES, PHISHING, BRUTEFORCING OR OTHER MEANS OF ATTACK AGAINST THE SERVICES OR ANY DIGITAL ASSET(S); OR (F) CONNECTING A WALLET ADDRESS THAT DOES NOT SUPPORT THE DIGITAL ASSET(S), IS INCOMPATIBLE WITH THE DIGITAL ASSET, OR OTHERWISE WHERE YOU ARE UNABLE TO ACCESS SUCH DIGITAL ASSETS.
YOU ARE SOLELY RESPONSIBLE FOR YOUR USE OF ANY THIRD PARTY PROGRAMS IN CONNECTION WITH GALXE COMPASS. THERE IS NO ASSURANCE THAT THE THIRD PARTY PROGRAMS OR ANY THIRD PARTY PROGRAM PROVIDER WILL BE AVAILABLE, FUNCTION OR OPERATE AS EXPECTED. YOU MAY NOT RECEIVE ANY REWARDS REGARDLESS OF THE AMOUNT OF TIME, EFFORT, ASSETS OR FUNDS THAT YOU UTILIZE IN CONNECTION WITH ANY SUCH THIRD PARTY PROGRAMS. IN ADDITION, IN THE EVENT THAT YOUR PARTICIPATE IN ANY SUCH THIRD PARTY PROGRAMS, YOUR FUNDS OR ASSETS MAY BE SUBJECT TO DEPRECIATION, HACKS, FRAUD, LOSSES (INCLUDING A TOTAL LOSS) OR OTHER DAMAGES. WE WILL BEAR NO RESPONSIBILITY WHATSOEVER WITH RESPECT TO ANY DECISION MADE BY YOU TO PARTICIPATE IN ANY THIRD PARTY PROGRAMS, WHETHER VIA THE THIRD PARTY PROGRAM PROVIDER OR OTHERWISE, OR ANY LOSSES, DAMAGES OR LIABILITIES ARISING THEREFROM.
NFTS ARE INTANGIBLE DIGITAL ASSETS. THEY EXIST ONLY BY VIRTUE OF THE OWNERSHIP RECORD MAINTAINED IN THE APPLICABLE BLOCKCHAIN NETWORK. ANY TRANSFER OF TITLE THAT MIGHT OCCUR IN ANY UNIQUE DIGITAL ASSET OCCURS ON THE DECENTRALIZED LEDGER WITHIN SUCH BLOCKCHAIN NETWORK. WE DO NOT GUARANTEE THAT WE CAN EFFECT THE TRANSFER OF TITLE OR RIGHT IN ANY NFTS OR OTHER DIGITAL ASSETS, OR THAT ANY ASSOCIATED PAYMENT WILL BE SUCCESSFUL.
Galxe is not responsible for any losses due to vulnerability or any kind of failure, abnormal behavior of any software (e.g., wallet, NFTS, "smart contract," etc.), blockchain(s) or any other feature(s) of the Services. Galxe is not responsible for losses due to any late reporting by Developers or representatives (or not reporting at all) of any issues with the blockchain(s) supporting any of the digital asset(s), including forks thereof, technical node issues or any other issues that result in any loss of funds.
Nothing in these Terms shall exclude or limit liability of either party for fraud, death or bodily injury caused by gross negligence, violation of laws, or any other activity that cannot be limited or excluded by legitimate means.
SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES IN CONTRACTS WITH CONSUMERS, SO THE ABOVE EXCLUSION MAY NOT APPLY TO YOU, SOLELY TO THE EXTENT SUCH EXCLUSION IS SO PROHIBITED BY APPLICABLE LAW.
# 21. Assumption of Risk
Volatility. The price and liquidity of blockchain-based assets, including digital asset(s) and NFTs, are extremely volatile and may be subject to fluctuations. Fluctuations in the price of other blockchain-based assets could materially and adversely affect digital asset(s). We cannot guarantee that purchasing any igital asset(s) will not result in the loss of money or other value.
Taxes. You are solely responsible for determining what, if any, taxes apply to your Digital Wallet(s). Neither Galxe nor any other Galxe Party is responsible for determining the taxes that apply to any Digital Wallet(s).
Digital assets / Cryptocurrency. The Services involve and/or rely upon certain blockchain technology, including decentralized, distributed public ledger(s), which offer many benefits, but also presents certain inherent risks that you assume by using the Services, including without limitation, that:
A lack of use or public interest in the creation and development of distributed ecosystems could negatively impact the development of those ecosystems and related applications, and could therefore also negatively impact the potential utility or value of digital asset(s).
The value of digital assets and NFTs are highly volatile and you may suffer a total loss of the value of such assets from time to time.
The regulatory regime governing blockchain technologies, digital assets, cryptocurrencies and/or so-called "tokens" is uncertain, and new regulations or policies may adversely affect the development of the Services and/or the utility of digital asset(s).
# 22. App Store
If you comply with these Terms, we grant to you a limited non-exclusive, non- transferable license, with no right to sublicense, to download and install the App on your personal computers, mobile handsets, tablets, wearable devices, and/or other devices and to run the App solely for your own personal non-commercial purposes. Except as expressly permitted in these Terms, you may not: (i) copy, modify or create derivative works based on the App; (ii) distribute, transfer, sublicense, lease, lend or rent the App to any third party; (iii) reverse engineer, decompile or disassemble the App (unless applicable law permits, despite this limitation); or (iv) make the functionality of the App available to multiple users through any means.
Apple App Store. This paragraph applies to any App that you acquire from the Apple App Store or use on an iOS device. Apple has no obligation to furnish any maintenance and support services with respect to the App. In the event of any failure of the App to conform to any applicable warranty, you may notify Apple, and Apple will refund the App purchase price to you (if applicable) and, to the maximum extent permitted by applicable law, Apple will have no other warranty obligation whatsoever with respect to the App. Apple is not responsible for addressing any claims by you or any third party relating to the App or your possession and use of it, including, but not limited to: (i) product liability claims; (ii) any claim that the App fails to conform to any applicable legal or regulatory requirement; and (iii) claims arising under consumer protection or similar legislation. Apple is not responsible for the investigation, defense, settlement and discharge of any third-party claim that your possession and use of the App infringe that third party's intellectual property rights. Apple and its subsidiaries are third-party beneficiaries of these Terms, and upon your acceptance of the Terms, Apple will have the right (and will be deemed to have accepted the right) to enforce these Terms against you as a third-party beneficiary thereof.
# 23. Limitation of Liability
TO THE FULLEST EXTENT PROVIDED BY LAW, IN NO EVENT WILL GALXE OR ITS AFFILIATES, OR ITS OR THEIR LICENSORS, SERVICE PROVIDERS, EMPLOYEES, CONTRACTORS, AGENTS, OFFICERS OR DIRECTORS, BE LIABLE FOR ANY INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES, INCLUDING BUT NOT LIMITED TO, PERSONAL INJURY, PAIN AND SUFFERING, EMOTIONAL DISTRESS, LOSS OF REVENUE, LOSS OF PROFITS, LOSS OF BUSINESS OR ANTICIPATED SAVINGS, LOSS OF USE, LOSS OF GOODWILL, LOSS OF DATA, LOSS OF DIGITAL ASSETS, LOSS OF ACCESS TO ANY DIGITAL WALLET, OR ANY OTHER DAMAGES OF ANY KIND, UNDER ANY LEGAL THEORY, ARISING OUT OF OR IN CONNECTION WITH YOUR USE, OR INABILITY TO USE, THE SERVICES, INCLUDING BUT NOT LIMITED TO ANY CONTENT ON THE SERVICES OR ANY OTHER WEBSITES AND MOBILE APPLICATIONS OR ANY ITEMS OBTAINED THROUGH THE SERVICES OR SUCH OTHER WEBSITES AND MOBILE APPLICATIONS, WHETHER CAUSED BY TORT (INCLUDING NEGLIGENCE), BREACH OF CONTRACT OR OTHERWISE, EVEN IF FORESEEABLE.
IN NO EVENT WILL GALXE'S AGGREGATE LIABILITY FOR ALL CLAIMS RELATING TO THE SERVICES, THE ACCESS TO AND USE OF THE SERVICE, CONTENT, DIGITAL ASSETS OR ANY PRODUCTS OR SERVICES PURCHASED ON THE SERVICES EXCEED THE GREATER OF (A) \$100 OR (B) THE AMOUNT RECEIVED BY GALXE FROM YOU RELATED TO THE DIGITAL ASSETS THAT ARE THE SUBJECT OF THE APPLICABLE CLAIM.
ANY CAUSE OF ACTION OR CLAIM YOU MAY HAVE ARISING OUT OF OR RELATING TO THESE TERMS OR THE SERVICES MUST BE COMMENCED WITHIN ONE (1) YEAR AFTER THE CAUSE OF ACTION ACCRUES, OTHERWISE, SUCH CAUSE OF ACTION OR CLAIM SHALL BE DEEMED PERMANENTLY WAIVED AND BARRED.
THIS SECTION DOES NOT AFFECT ANY LIABILITY THAT CANNOT BE EXCLUDED OR LIMITED UNDER APPLICABLE LAW. BECAUSE SOME STATES OR JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR THE LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, IN SUCH STATES OR JURISDICTIONS THE ABOVE LIMITATIONS AND EXCLUSIONS MAY NOT APPLY TO YOU. IN SUCH STATES OR JURISDICTIONS, OUR LIABILITY IS LIMITED TO THE EXTENT PERMITTED BY LAW, THEREBY MINIMIZING OUR LIABILITY TO YOU TO THE LOWEST AMOUNT PERMITTED BY APPLICABLE LAW.
# 24. Dispute Resolution
This Section includes an arbitration agreement and an agreement that all claims will be brought only in an individual capacity (and not as a class action or other representative proceeding). Please read it carefully.
Informal Process. You agree that in the event of any dispute between you and Galxe, you will first contact Galxe and make a good faith sustained effort to resolve the dispute before resorting to more formal means of resolution, including without limitation any court action.
Agreement to Arbitrate. Any dispute, controversy, difference or claim arising out of or relating to this contract, including the existence, validity, interpretation, performance, breach or termination thereof or any dispute regarding non-contractual obligations arising out of or relating to it shall be referred to and finally resolved by arbitration administered by the BVI International Arbitration Centre (BVIIAC) under the UNCITRAL Arbitration Rules in force when the Notice of Arbitration is submitted, as modified by the IAC Procedures for the Administration of Arbitration under the UNCITRAL Arbitration Rules.\*
The Tribunal shall consist of 1 arbitrator. The language of the arbitration shall be English.
Class Action Waiver. Any Claim must be brought in the respective party's individual capacity, and not as a plaintiff or class member in any purported class, collective, representative, multiple plaintiff or similar proceeding ("Class Action"). The parties expressly waive any ability to maintain any Class Action in any forum. If the Claim is subject to arbitration, the arbitrator will not have authority to combine or aggregate similar claims or conduct any Class Action nor make an award to any person or entity not a party to the arbitration. Any claim that all or part of this Class Action Waiver is unenforceable, unconscionable, void or voidable may be determined only by a court of competent jurisdiction and not by an arbitrator. The parties understand that any right to litigate in court, to have a judge or jury decide their case or to be a party to a class or representative action is waived, and that any claims must be decided individually, through arbitration.
Waiver of Jury Trial. If for any reason a claim proceeds in court rather than in arbitration, you and Galxe each waive any right to a jury trial.
# 25. Miscellaneous
Governing Law and Venue. These Terms, your access to and use of the Services and Content, and your participation in the Services, shall be governed by and construed and enforced in accordance with the laws of the British Virgin Islands, without regard to conflict of law rules or principles of the British Virgin Islands, or any other jurisdiction that would cause the application of the laws of any other jurisdiction. Any dispute between the parties that is not subject to arbitration or cannot be heard in court located in the British Virgin Islands.
Severability. If any term, clause or provision of these Terms is held invalid or unenforceable, then that term, clause or provision will be severable from these Terms and will not affect the validity or enforceability of any remaining part of that term, clause or provision, or any other term, clause or provision of these Terms.
Waver. If we fail to insist that you perform any of your obligations under these Terms, or if we do not enforce our rights against you, or if we delay in doing so, that will not mean that we have waived our rights against you and will not mean that you do not have to comply with those obligations. If we do waive a default by you, we will only do so in writing, and that will not mean that we will automatically waive any later default by you.
Assignability. These Terms are personal to you, and are not assignable, transferable or sublicensable by you except with Galxe's express written consent.
Notices. All notices under these Terms will be in writing and will be deemed to have been duly given when received, if personally delivered or sent by certified or registered mail, return receipt requested; when receipt is electronically confirmed, if transmitted by facsimile or e-mail; or the day after it is sent, if sent for next day delivery by recognized overnight delivery service.
# Official Channels
Source: https://docs.galxe.com/about/official-channels
Find out the official social channels of Galxe
## Discord
[https://discord.gg/galxe](https://discord.gg/galxe)
## X
[https://x.com/galxe](https://x.com/galxe)
## Telegram
[https://t.me/Galxe](https://t.me/Galxe)
[https://t.me/GalxeApp](https://t.me/GalxeApp)
[https://t.me/GalxePostBot](https://t.me/GalxePostBot)
# Sign in with Galxe
Source: https://docs.galxe.com/galxe-id/galxe-id-integration/galxe-id-oauth
Integrating **Sign in with Galxe** in your app to get access to 14 million users of Galxe ID
## Sign in with Galxe - Demo[](#demo "Direct link to heading")
Please see the [Demo](https://demo.tian.fyi/) and its [source code](https://github.com/oyyblin/galxe-id-sdk-oauth-demo).
## Visual Guidelines
Make sure you [use this resource and follow our brand guidelines](https://gal.xyz/sign-in-with-galxe-visuals) to implement **Sign in with Galxe**.
## Getting Started[](#getting-started "Direct link to heading")
To get started, please apply for a client ID by contacting our live chat support from your dashboard management page.
## OAuth[](#oauth "Direct link to heading")
Galxe's OAuth implementation supports the standard [authorization code grant type](https://tools.ietf.org/html/rfc6749#section-4.1) for apps that don't have access to a web browser.
### Authorization flow[](#authorization-flow "Direct link to heading")
The request flow to authorize users for your app is:
1. Users are redirected to request their Galxe identity.
2. Users are redirected back to your site by Galxe.
3. Your app accesses the API with the user's access token.
### 1. Request a user's Galxe identity[](#1-request-a-users-galxe-identity "Direct link to heading")
#### URL[](#url "Direct link to heading")
```
GET https://app.galxe.com/oauth
```
```
REDIRECT
https://app.galxe.com/oauth?client_id=${CLIENT-ID}&scope=${SCOPE}&redirect_uri=${REDIRCT-URI}&state=${STATE}
```
**scope whitelist**:
* Email
* Twitter
* Discord
* Github
* Telegram
* EVMAddress
* SolanaAddress
* SeiAddress
* AptosAddress
* InjectiveAddress
* FlowAddress
* GalxeID
#### Parameters[](#parameters "Direct link to heading")
| Name | Type | Description |
| ----------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| client\_id | string | **Required**. The client ID you received from Galxe when you registered. |
| scope | string | **Required**. A space-delimited list of scopes. If not provided, scope defaults to an empty list for users that have not authorized any scopes for the application. |
| redirect\_uri | string | **Required**. The URL in your application where users will be sent after authorization, also known as callback url. |
| state | string | **Required**. An unguessable random string. It is used to protect against cross-site request forgery attacks. |
| code\_challenge | string | PKCE (Proof Key for Code Exchange) is an extension to the Authorization Code flow to prevent CSRF and authorization code injection attacks. PKCE is not a replacement for a client secret, and PKCE is recommended even if a client is using a client secret. |
| code\_challenge\_method | string | Encoding method, plain or S256 (sha256), S256 is recommended. |
#### Response[](#response "Direct link to heading")
By default, the response will add the following parameter to your `redirect_uri`:
```
code=${CODE}&state=${STATE}
```
### 2. Get Access Token[](#2-get-access-token "Direct link to heading")
If the user accepts your request, Galxe redirects back to your site with a temporary `code` in a code parameter as well as the state you provided in the previous step in a `state` parameter. The temporary code will expire after **10 minutes**. If the states don't match, then a third party created the request, and you should abort the process.
Exchange this `code` for an access token.
#### URL[](#url-1 "Direct link to heading")
```bash theme={null}
Content-Type:application/x-www-form-urlencoded
POST https://api.galxe.com/oauth/auth/2/token
```
```bash theme={null}
curl -d 'client_id=${CLIENT-ID}&client_secret=${CLIENT-SECRET}&code=${CODE}&grant_type=authorization_code' -H "Content-Type:application/x-www-form-urlencoded" -X POST https://api.galxe.com/oauth/auth/2/token
```
#### Parameters[](#parameters-1 "Direct link to heading")
| Name | Type | Description |
| -------------- | ------ | --------------------------------------------------------------------------- |
| client\_id | string | **Required**. The client ID you received from Galxe for your OAuth App. |
| client\_secret | string | **Required**. The client secret you received from Galxe for your OAuth App. |
| code | string | **Required**. The code you received as a response to OAuth Authorize Step. |
| code\_verifier | string | Plain string of code\_challenge, only used when requiring code\_challenge. |
#### Response[](#response-1 "Direct link to heading")
By default, the response takes the following form:
```json theme={null}
{
"access_token": "OTJLYTIWNMQTYJY1ZC0ZOGQ2LTGYMDITNWQXZWJKNTA4YZAA",
"expires_in": 86400,
"refresh_token": "NGM5OWUXNDKTNTEZOC01NZBMLWEXMGUTMDUYZGJMNZI3YME0",
"scope": "Twitter",
"token_type": "Bearer"
}
```
### 3. Refresh Access Token[](#3-refresh-access-token "Direct link to heading")
#### URL[](#url-2 "Direct link to heading")
```bash theme={null}
Content-Type:application/x-www-form-urlencoded
POST https://api.galxe.com/oauth/auth/2/token
```
```bash theme={null}
curl -d 'grant_type=refresh_token&refresh_token=${REFRESH-TOKEN}&client_id=${CLIENT-ID}&client_secret=${CLIENT-SECRET}' -H "Content-Type:application/x-www-form-urlencoded" -X POST https://api.galxe.com/oauth/auth/2/token
```
#### Parameters[](#parameters-2 "Direct link to heading")
| Name | Type | Description |
| -------------- | ------ | ---------------------------------------------------------------------------------------------------------------------- |
| refresh\_token | string | **Required**. The token generated when the Galxe App owner enables expiring tokens and issues a new user access token. |
| grant\_type | string | **Required**. Value must be refresh\_token (required by the OAuth specification). |
| client\_id | string | **Required**. The client ID for Galxe App. |
| client\_secret | string | **Required**. The client secret for Galxe App. |
#### Response[](#response-2 "Direct link to heading")
```json theme={null}
{
"access_token": "NTLMMJKYMMQTZJZJYI0ZZGFLLWE5NZMTMZAZMDY3YWMWNMI4",
"expires_in": 86400,
"refresh_token": "NGQXZGVJZDCTNTQ4YY01NTEZLTHMNTMTYJZHMWZIYJUZMJE3",
"scope": "Twitter Discord",
"token_type": "Bearer"
}
```
### 4. Get Access Token Detail[](#4-get-access-token-detail "Direct link to heading")
#### URL[](#url-3 "Direct link to heading")
```bash theme={null}
Authorization: Bearer ${ACCESS-TOKEN}
GET https://api.galxe.com/oauth/api/2/token
```
```bash theme={null}
curl -H "Authorization: Bearer ${ACCESS-TOKEN}" https://api.galxe.com/oauth/api/2/token
```
#### Parameters[](#parameters-3 "Direct link to heading")
| Name | Type | Description |
| ------------- | ------ | ---------------------------------- |
| access\_token | string | **Required**. Append it to header. |
#### Response[](#response-3 "Direct link to heading")
```json theme={null}
{
"client_id": "client_id",
"expires_at": "2022-08-31 16:00:22.666401 +0800 CST",
"scope": "twitter discord"
}
```
### 5. Use the access token to access the API[](#5-use-the-access-token-to-access-the-api "Direct link to heading")
#### URL[](#url-4 "Direct link to heading")
```
Authorization: Bearer ${ACCESS-TOKEN}
GET https://api.galxe.com/oauth/api/2/user
```
```bash theme={null}
curl -H "Authorization: Bearer ${ACCESS-TOKEN}" https://api.galxe.com/oauth/api/2/user?scope=Twitter%20Discord
```
#### Parameters[](#parameters-4 "Direct link to heading")
| Name | Type | Description |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| access\_token | string | **Required**. Append it to request header. |
| scope | string | A space-delimited list of scopes of user data that your APP required. If not set, will set to access token related scope by default. |
#### Response[](#response-4 "Direct link to heading")
```json theme={null}
{
"TwitterUsername": "twitter_username",
"TwitterUserID": "twitter_userid",
"DiscordUsername": "discord_username"
"DiscordUserID": "discord_userid"
}
```
# Galxe Passport
Source: https://docs.galxe.com/galxe-id/galxe-passport/introduction
Galxe Passport is the most trusted Web3 identity service for proof of personhood
## What is Galxe Passport?
Galxe Passport is your universal identity for Web3 adventures. It stores your identity information securely and anonymously. You will be able to use this as your universal identity across different applications for compliance purposes. You will also get your unique Galxe Passport Soulbound Token in your wallet to be distinguished as a verified individual. Enabling our partners to prevent Sybil attacks.
Galxe Passport was created to be a secure, private way for users to store data. Users’ private information will be encrypted with their password. These data are only accessible to the user, all others (including Galxe) can only access these data upon the user’s permission. Users who want to obtain a Soulbound Token can do so by going through the verification process on Galxe which will then allow them to mint and claim the Galxe Passport Token.
## Technical documentation
Galxe Passport was designed on the principle that you have the right to your personal information — you should get to decide where, how, and with whom it’s shared. You should also be able to prove your personhood. We are committed to protecting your privacy and we have built Galxe Passport with control, security, and transparency in mind. In this section, we will describe in detail how we process and store encrypted user PII (Personal Identifiable Information).
### Tenets
1. Galxe Passport’s PII should be fully managed by their owners and kept private safely - your data is never stored in plain text and will not be accessible by anyone (including Galxe) without your explicit permission.
2. Owners can share their Galxe Passport data with external parties under strict consent by the owners only - using valid, non-replayable signatures and client side decryption with user password.
3. When external parties receive Galxe Passport data, they should be able to verify its data integrity.
### Data Flow
### 1 - Sumsub identity verification
**Sumsub** is the third-party vendor that helps run algorithms and check whether your ID is valid. They collect the identity information directly from you because they need to provide identity verification.
When a user is prompted with a **Sumsub** verification embedded on **galxe.com**, we generate an UUID for the user and pass it to **Sumsub**. **Sumsub** uses this UUID to uniquely identifies a person, and group all verifications under the same UUID together. For now this UUID is stored in our database as user’s “Vendor Reference ID”.
When the verification is approved, **Sumsub** informs Galxe and user now proceeds to the next step: constructing the Galxe passport.
### 2 - Constructing Galxe Passport
User on Galxe is now guided to construct Galxe Passport from PII collected from their approved verification on **Sumsub**. There are 3 steps with two separate signatures needed:
1. (signing needed) Retrieve PII from **Sumsub**, signed by Galxe witness to ensure its integrity - let’s call this a signed credential
2. Encrypt signed credential using user’s own strong password of choice
3. (signing needed) Pass the encrypted data back to Galxe for storage, and create the Galxe Passport
### 2.1 - Retrieving PII from Sumsub
Using the UUID (Vendor Reference ID) generated for the user, we are able to retrieve the complete verification result from **Sumsub**. Example:
```json theme={null}
{
"id": "680123456789abcdef123456", // applicant id in Sumsub
"createdAt": "2020-06-24 05:05:14",
"clientId": "your_cool_id",
"inspectionId": "680123456789abcdef123456",
"externalUserId": "12345678-1234-5678-1234-123456789012", // vendor reference id in Galxe.com
"fixedInfo": {
"firstName": "John",
"lastName": "Doe"
},
"info": {
"firstName": "John",
"firstNameEn": "John",
"lastName": "Doe",
"lastNameEn": "Doe",
"dob": "1977-07-17",
"country": "US",
"idDocs": [
{
"idDocType": "ID_CARD",
"country": "US",
"firstName": "John",
"firstNameEn": "John",
"lastName": "Doe",
"lastNameEn": "Doe",
"validUntil": "2030-12-31",
"number": "I1234562",
"dob": "1977-07-17",
"gender": "M"
}
]
},
"email": "johndoe@example.com",
"applicantPlatform": "Android",
"review": {
"elapsedSincePendingMs": 115879,
"elapsedSinceQueuedMs": 95785,
"reprocessing": true,
"levelName": "basic-kyc",
"createDate": "2020-06-24 05:11:02+0000",
"reviewDate": "2020-06-24 05:12:58+0000",
"reviewResult": {
"reviewAnswer": "GREEN"
},
"reviewStatus": "completed"
},
"lang": "en",
"type": "individual"
}
```
Also, we can fetch user's document images, Example:
```json theme={null}
{
"items": [
{
"id": "1583009672",
"addedDate": "2020-06-24 05:13:22",
"fileMetadata": {
"fileName": "example_id_doc_name1.jpg",
"fileType": "jpeg"
},
"idDocDef": {
"country": "US",
"idDocType": "DRIVERS",
"idDocSubType": "FRONT_SIDE"
},
"reviewResult": {
"reviewAnswer": "GREEN"
}
},
{
"id": "1647256602",
"addedDate": "2020-06-24 05:13:26",
"fileMetadata": {
"fileName": "example_id_doc_name2.jpg",
"fileType": "jpeg"
},
"idDocDef": {
"country": "US",
"idDocType": "DRIVERS",
"idDocSubType": "BACK_SIDE"
},
"reviewResult": {
"reviewAnswer": "GREEN"
}
},
{
"id": "1779050422",
"addedDate": "2020-06-24 05:14:13",
"fileMetadata": {
"fileName": "liveness_photo_203016ec-3abe-4297-89b2-e42cc4432532.jpg",
"fileType": "jpeg"
},
"idDocDef": {
"country": "US",
"idDocType": "SELFIE"
},
"reviewResult": {
"reviewAnswer": "GREEN"
}
}
],
"totalItems": 3
}
```
\
Galxe proceeds to first clean up the data into our own Galxe Passport format. Example:
```cs theme={null}
{
'evm-address': '0x1234567890123456789012345678901234567890',
governmentIDs: [
{
'first-name': 'John',
'last-name': 'Doe',
'birthdate': '1977-07-17',
'nationality': '',
'document-number': 'I1234562',
'sex': 'M',
'country-code': 'US',
'id-doc-type': 'DRIVERS',
'front-photo-key': '1583009672', // sumsub id for front-side ID doc
'back-photo-key': '1647256602', // sumsub id for back-side ID doc
'identification-number': 'I1234562'
}
],
selfie: {
'center-photo-key': '1779050422' // sumsub id for selfie image
},
'passport-version': 'v2.1',
'vendor_reference_id': '12345678-1234-5678-1234-123456789012'
}
```
Galxe then runs the following steps:
1. Generate a 32-byte `salt` from a crypto-safe random number generator
2. Marshal (`user_address`, `salt`, `passport_data`) into `canon_json_str`, a canonical JSON string, then compute its hash using `hash = keccak256(cannon_json_str)`
3. Ask Galxe witness to sign the hash: `signature = ECDSA.sign(witness_priv_key, hash)`
4. Constructed signed credential `signed_cred = json.Marshal(SignedCred{Body: canon_json_str, Signature: signature})`
5. Return `signed_cred` to frontend
### 2.2 - User encryption on Galxe frontend
On Galxe frontend, user now inputs their strong password of choice to encrypt the signed credential using `AES-256-GCM`. Example code:
```
const password_str = "strong_password_omg";
// use the 32-byte hash from a SHA256 on user’s password of choice
const password = keccak256(password_str);
const iv = crypto.randomBytes(12);
const cipher = crypto.createCipheriv("aes-256-gcm", password, iv);
const encrypted = cipher.update(signed_cred);
cipher.final('base64');
const data = "0x" + Buffer.concat([iv, encrypted, cipher.getAuthTag()]).toString("hex");
```
Note that all user data is encrypted with your password. Galxe does not have access to and cannot view or share your information without your permission and password. Galxe does not have the password to decrypt the encrypted PII. At this point, the user is ready to proceed to the next step.
### 2.3 - Create Galxe Passport using the user encrypted data
In this step, user signs another message with their wallet and pass the encrypted data back to Galxe for storage, and create the Galxe Passport. Once this is completed, Galxe deletes the UUID that links **Sumsub**’s identity information to your evm address. Now the only place that UUID exists outside **Sumsub** is inside your encrypted Galxe Passport.
### 3 - Mint Galxe Passport Soulbound Token
Once Galxe Passport is created and safely stored, the owner user can now mint the Galxe Passport SBT - a non-transferrable NFT that marks this user’s verification completion status through Galxe. SBT contract can be found under: [https://bscscan.com/address/0xe84050261cb0a35982ea0f6f3d9dff4b8ed3c012](https://bscscan.com/address/0xe84050261cb0a35982ea0f6f3d9dff4b8ed3c012)
Tokens in this contract do not contain any PII. Their main purposes is for other partners on Galxe to use as a proof-of-human mechanism for sybil attack prevention.
## FAQ
Q: How will my identity information be stored?
A: Your identity information will be encrypted with your password. Galxe never stores these data in plain text and will not have access to these data.
Q: Who can access my identity information?
A: Because Galxe does not store your password, only you can decrypt these data with your password. No one, including Galxe, has the access to your identity information without your permission.
Q: How can I use my Galxe Passport?
A: Partners(eg. IDO or INO platforms) who integrate Galxe ID SDK may ask for your identity information for compliance reasons. By granting them access to your Galxe Passport’s identity information, you do not need to complete verification process on their sites for additional times. Other partners may use Galxe Passport SBT as a proof-of-human mechanism to prevent sybil attack prevention.
Q: If I participate a campaign on Galxe which requires Galxe Passport Holder credential, am I giving away my identity information?
A: No. Galxe Passport Holder credential only looks at your Galxe Passport NFT holding in your wallet. Galxe Passport NFT is minted on BNB Chain with [this](https://bscscan.com/token/0xe84050261cb0a35982ea0f6f3d9dff4b8ed3c012) contract address. Participating in these campaigns will not disclose your identity information.
Q: What happens if I lose my Galxe Passport password?
A: Because Galxe does NOT store your password, there is no way to recover your password if you lose it. If you lose your password, you can still use your Galxe Passport as a proof-of-human NFT, however, you will NOT be able to decrypt your personal data to share with other third parties for compliance purposes.
Q: What’s **Sumsub**’s role in the process?
A: **Sumsub** is the third party vendor that helps run algorithm and check whether your ID is valid. They do have your identity information because they need to check duplicated IDs in the system. However, they do not know which identity belongs to which address.
Q: Will I remain anonymous after I mint Galxe Passport?
A: Neither Galxe nor **Sumsub** has the mapping relationship between wallet address and identity information. You will remain completely anonymous after the minting of Galxe Passport.
Q: Am I required to mint Galxe Passport in order to use Galxe?
A: No. None of the features on Galxe will require you to mint Galxe Passport. Neither does Galxe require any of the partner to use Galxe Passport Holder credential in their campaigns. Galxe Passport Holder credential functions in the same way as any other credential in the network. It’s at campaign creators’ sole discretion whether to include Galxe Passport Holder credential as a requirement in their campaigns.
Q: What happens if any government agencies request user information from Galxe?
A: Galxe can never disclose your information to anyone, including government agencies, without your permission because Galxe does not store your information in plain text, nor does it have the password to decrypt the encrypted identity information.
# Introduction
Source: https://docs.galxe.com/galxe-id/introduction
Galxe ID is your universal Web3 identity service
* Galxe ID can be your universal username that will represent your multichain/multiwallet identities in Web3.
* You can display the credentials collected in the Web3 world and showcase the history of your achievements.
* As a metaverse DID, developers can integrate Galxe ID toolkit and offer customized features to users based on their digital credentials, or simply enrich user profiles in the product. This will open up a lot of possibilities and redefine the future of Web3.
* More features will be added, and soon you will be able to use the Galxe ID in Galxe's extensive partner network.
## Create your Galxe ID[](#claim-your-galxe-id "Direct link to heading")
1. Visit [https://app.galxe.com/](https://app.galxe.com/)
2. Log in with your wallet & set your username
3. Connect other identities with your Galxe ID in Account Settings
4. Done 🎉 - now you will be able to see eligible credentials attached to your Galxe ID
## Wallets[](#wallets "Direct link to heading")
You will be able to link your wallet addresses from supported blockchain networks with your Galxe ID. For the best developer experience, we recommend you to use an EVM wallet address as the primary address.
## Twitter integration[](#twitter-integration "Direct link to heading")
On Galxe, we have specially designed the task-based campaign module w/ Twitter integration. It can be used to power various Twitter based campaigns, which also requires users to link their Twitter accounts to Galxe ID.
To accomplish that, simply follow the 2 steps after you click “Verify Twitter Account” Button.
## Discord integration[](#discord-integration "Direct link to heading")
Some NFTs can only be claimed with a Discord entry, and here’s when linking your Discord comes in handy.
Click "Connect Discord Account" and it will open up another Discord application tab. On the new tab, click on "Authorise", and your Discord is now connected.
## Github integration[](#github-integration "Direct link to heading")
Some NFTs can only be claimed with a Github entry. To link with Github, you can click on "Verify Github Account", and follow the steps to create a unlisted Gist and verify with Galxe.
## Integrate Galxe ID SDK with Your Application
To learn more about how you can integrate Galxe ID in your own app, [visit this article](https://docs.galxe.com/galxe-id/galxe-id-integration/galxe-id-oauth).
# Credential API Reference
Source: https://docs.galxe.com/galxe-integration/api-reference/credential
Query user credentials and check eligibility for verification requirements
## Overview
The Credential API provides **read-only** access to verify user eligibility and query credential information.
## Core Queries
### Get Credential Information
```graphql theme={null}
query GetCredential($credId: ID!) {
credential(id: $credId) {
id
name
description
credType
credSource
chain
referenceLink
itemCount
lastUpdate
lastSync
syncStatus
curatorSpace {
id
name
}
}
}
```
### Check User Eligibility
```graphql theme={null}
query CheckEligibility($credId: ID!, $address: String!, $campaignId: ID) {
credential(id: $credId) {
id
name
eligible(address: $address, campaignId: $campaignId)
credType
credSource
syncStatus
lastSync
}
}
```
**Variables**:
```json theme={null}
{
"credId": "312969464",
"address": "0x1234567890123456789012345678901234567890",
"campaignId": "GChdWUjXX3"
}
```
**Response**:
```json theme={null}
{
"data": {
"credential": {
"id": "312969464",
"name": "Twitter Follower Verification",
"eligible": 1,
"credType": "TWITTER",
"credSource": "TWITTER_FOLLOW",
"syncStatus": "SYNCED",
"lastSync": 1699200000
}
}
}
```
**Eligibility Values**:
* `1` - User has the credential
* `0` - User does not have the credential
## Field Reference
### Key Fields
| Field | Type | Description |
| ------------------------------- | ------------- | ---------------------------------- |
| `id` | `ID!` | Credential's unique identifier |
| `name` | `String!` | Human-readable credential name |
| `credType` | `CredType!` | Credential platform/type |
| `credSource` | `CredSource!` | Verification method |
| `eligible(address, campaignId)` | `Int` | User eligibility check (0 or 1) |
| `syncStatus` | `SyncStatus!` | Data synchronization status |
| `itemCount` | `Int` | Total number of credential holders |
### Credential Types
| Type | Description |
| ---------------- | ------------------------------- |
| `TWITTER` | Twitter account verification |
| `DISCORD` | Discord membership verification |
| `EVM_ADDRESS` | Ethereum-compatible addresses |
| `SOLANA_ADDRESS` | Solana wallet addresses |
| `GITHUB` | GitHub account verification |
| `EMAIL` | Email address verification |
### Credential Sources
| Source | Description |
| --------------------- | ---------------------------- |
| `TWITTER_FOLLOW` | Twitter follow verification |
| `DISCORD_MEMBER` | Discord server membership |
| `CONTRACT_NFT_HOLDER` | NFT ownership verification |
| `WALLET_BALANCE` | Token balance requirements |
| `QUIZ` | Quiz completion verification |
| `API` | Custom API verification |
### Sync Status
| Status | Description |
| --------- | ----------------------------------- |
| `SYNCED` | Data is current and reliable |
| `SYNCING` | Data is being updated, may be stale |
## Integration Patterns
### Basic Verification
```bash theme={null}
curl -X POST https://graphigo-business.prd.galaxy.eco/query \
-H "Content-Type: application/json" \
-H "access-token: YOUR_ACCESS_TOKEN" \
-d '{
"query": "query CheckEligibility($credId: ID!, $address: String!) { credential(id: $credId) { name eligible(address: $address) syncStatus } }",
"variables": { "credId": "312969464", "address": "0x..." }
}'
```
### Quest-Specific Context
When checking eligibility for a specific quest, include the `campaignId` parameter:
```graphql theme={null}
eligible(address: $address, campaignId: $campaignId)
```
## Best Practices
1. **Check Sync Status**: Always verify `syncStatus` is `SYNCED` before relying on eligibility results
2. **Handle Quest Context**: Use `campaignId` parameter for quest-specific verifications
3. **Cache Results**: Cache eligibility results for 5-10 minutes to reduce API calls
4. **Error Handling**: Handle invalid credential IDs and network errors gracefully
## Common Errors
| Error | Cause | Solution |
| ---------------------- | ------------------------- | ----------------------------- |
| `Credential not found` | Invalid credential ID | Verify credential ID exists |
| `Address not provided` | Missing address parameter | Include user address in query |
| `Rate limit exceeded` | Too many requests | Implement retry logic |
| `Invalid access token` | Bad/expired token | Regenerate access token |
## Next Steps
* **[User Verification Guide](/galxe-integration/guides/user-verification)** - Implementation patterns
* **[Quest API Reference](/galxe-integration/api-reference/quest)** - Quest requirements
* **[Authentication](/galxe-integration/getting-started/authentication)** - Access token setup
# Quest API Reference
Source: https://docs.galxe.com/galxe-integration/api-reference/quest
Query quest information and check user eligibility for quest requirements
## Overview
The Quest API provides access to quest information, user eligibility verification, and quest metadata.
## Core Queries
### Get Quest Details
```graphql theme={null}
query GetQuest($id: ID!) {
quest(id: $id) {
id
name
type
status
description
startTime
endTime
cap
participantsCount
loyaltyPoints
gasType
space {
id
name
}
chain
}
}
```
### List Space Quests
```graphql theme={null}
query GetSpaceQuests($input: ListQuestInput!) {
quests(input: $input) {
totalCount
pageInfo {
hasNextPage
endCursor
}
list {
id
name
type
status
participantsCount
loyaltyPoints
startTime
endTime
}
}
}
```
**Variables**:
```json theme={null}
{
"input": {
"spaceId": "40",
"statuses": ["Active", "NotStarted"],
"types": ["Drop", "Points"],
"first": 20
}
}
```
### Check User Eligibility
```graphql theme={null}
query CheckQuestEligibility($questId: ID!, $address: String!) {
quest(id: $questId) {
id
name
status
credentialGroups(address: $address) {
id
name
conditionRelation
conditions {
expression
eligible
}
rewards {
expression
eligible
rewardType
rewardCount
}
}
}
}
```
**When all `conditions.eligible` are `true`, the user meets quest requirements.**
## Field Reference
### Quest Status
| Status | Description |
| ------------ | ---------------------------------------- |
| `Draft` | Quest in development, not visible |
| `Active` | Quest is live and accepting participants |
| `NotStarted` | Quest scheduled but not started |
| `Expired` | Quest period has ended |
| `CapReached` | Maximum participants reached |
| `Deleted` | Quest has been removed |
### Quest Types
| Type | Description |
| -------------- | ---------------------------- |
| `Drop` | Standard quest with rewards |
| `MysteryBox` | Random reward quest |
| `Airdrop` | Token distribution quest |
| `Points` | Loyalty points reward |
| `ExternalLink` | External website integration |
### Gas Types
| Type | Description |
| --------- | --------------------- |
| `Gas` | User pays gas fees |
| `Gasless` | Galxe covers gas fees |
### Key Fields
| Field | Type | Description |
| --------------------------- | ------------------- | ------------------------------ |
| `id` | `ID!` | Quest's unique hash ID |
| `name` | `String!` | Quest display name |
| `status` | `QuestStatus!` | Current quest status |
| `participantsCount` | `Int!` | Number of participants |
| `loyaltyPoints` | `Int!` | Points awarded for completion |
| `credentialGroups(address)` | `[CredentialGroup]` | User-specific eligibility data |
## Integration Patterns
### Basic Quest Validation
```bash theme={null}
curl -X POST https://graphigo-business.prd.galaxy.eco/query \
-H "Content-Type: application/json" \
-H "access-token: YOUR_ACCESS_TOKEN" \
-d '{
"query": "query GetQuest($id: ID!) { quest(id: $id) { name status participantsCount cap loyaltyPoints } }",
"variables": { "id": "GChdWUjXX3" }
}'
```
### Quest Status Validation
Check these conditions before allowing participation:
1. `status` must be `"Active"`
2. `participantsCount` must be less than `cap` (if cap > 0)
3. Current time must be between `startTime` and `endTime`
### User Eligibility Flow
1. Call `credentialGroups(address: $userAddress)`
2. Check each group's `conditions.eligible` values
3. If `conditionRelation` is `"ALL"`, all conditions must be `true`
4. If `conditionRelation` is `"ANY"`, at least one condition must be `true`
## Best Practices
1. **Status Validation**: Always check quest status before showing participation UI
2. **Capacity Check**: Verify `participantsCount < cap` for available spots
3. **Time Validation**: Ensure current time is within quest period
4. **Error Handling**: Handle quest not found and permission errors
5. **Caching**: Cache quest details for 1-5 minutes to reduce API calls
## Common Errors
| Error | Cause | Solution |
| ----------------------- | --------------------- | ----------------------- |
| `Quest not found` | Invalid quest ID | Verify quest ID exists |
| `Quest is private` | No access permissions | Check quest permissions |
| `Rate limit exceeded` | Too many requests | Implement retry logic |
| `Invalid status filter` | Wrong enum value | Use valid status values |
## Next Steps
* **[Quest Integration Guide](/galxe-integration/guides/quests)** - Complete implementation patterns
* **[Credential API Reference](/galxe-integration/api-reference/credential)** - User verification
* **[Authentication](/galxe-integration/getting-started/authentication)** - Access token setup
# Space API Reference
Source: https://docs.galxe.com/galxe-integration/api-reference/space
Query space information and loyalty points rankings
## Overview
The Space API provides access to space information and loyalty points leaderboards.
## Core Queries
### Get Space Information
```graphql theme={null}
query GetSpace($spaceId: Int!) {
space(id: $spaceId) {
id
name
description
}
}
```
### Get Loyalty Points Rankings
```graphql theme={null}
query GetSpaceLeaderboard($spaceId: Int!, $cursorAfter: String, $sprintId: Int) {
space(id: $spaceId) {
loyaltyPointsRanks(
cursorAfter: $cursorAfter
sprintId: $sprintId
) {
totalCount
pageInfo {
hasNextPage
endCursor
}
list {
rank
points
address {
username
address
avatar
}
}
}
}
}
```
**Variables**:
```json theme={null}
{
"spaceId": 40,
"cursorAfter": null,
"sprintId": null
}
```
### Alternative: Direct Rankings Query
```graphql theme={null}
query GetSpaceLoyaltyRanks($spaceId: Int!, $sprintId: Int, $cursorAfter: String) {
spaceLoyaltyPointsRanks(
spaceId: $spaceId
sprintId: $sprintId
cursorAfter: $cursorAfter
) {
totalCount
pageInfo {
hasNextPage
endCursor
}
list {
rank
points
address {
username
address
avatar
}
}
}
}
```
## Field Reference
### Key Fields
| Field | Type | Description |
| -------------------- | -------------------- | ------------------------- |
| `id` | `String!` | Space's unique identifier |
| `name` | `String!` | Space display name |
| `description` | `String` | Space description |
| `loyaltyPointsRanks` | `LoyaltyPointsRanks` | Leaderboard data |
### Pagination Parameters
| Parameter | Status | Description |
| -------------- | ------------- | ----------------------------------- |
| `cursorAfter` | ✅ Current | Start pagination after this cursor |
| `cursorBefore` | ✅ Current | Start pagination before this cursor |
| `sprintId` | Optional | Filter by specific sprint |
| `first` | ⚠️ Deprecated | Use cursor-based pagination |
| `after` | ⚠️ Deprecated | Use cursor-based pagination |
### LoyaltyPointsRank Fields
| Field | Type | Description |
| --------- | --------- | ------------------------------ |
| `rank` | `Int!` | User's position in leaderboard |
| `points` | `Int!` | User's total loyalty points |
| `address` | `Address` | User profile information |
## Integration Patterns
### Basic Leaderboard Query
```bash theme={null}
curl -X POST https://graphigo-business.prd.galaxy.eco/query \
-H "Content-Type: application/json" \
-H "access-token: YOUR_ACCESS_TOKEN" \
-d '{
"query": "query GetLeaderboard($spaceId: Int!) { space(id: $spaceId) { name loyaltyPointsRanks(cursorAfter: null) { totalCount list { rank points address { username } } } } }",
"variables": { "spaceId": 40 }
}'
```
### Sprint-Specific Rankings
To get rankings for a specific sprint period, include the `sprintId` parameter:
```graphql theme={null}
loyaltyPointsRanks(sprintId: $sprintId, cursorAfter: $cursorAfter)
```
### Pagination Pattern
1. Start with `cursorAfter: null`
2. Use `pageInfo.endCursor` from response as next `cursorAfter`
3. Continue until `pageInfo.hasNextPage` is `false`
## User Position Lookup
**No Direct User Lookup**: The B2B API does not provide a direct user position lookup field like `addressLoyaltyPoints`. To find a specific user's rank, you must paginate through the leaderboard pages.
### Search Strategy
1. **Limited Search**: Search first 10-20 pages for UI responsiveness
2. **Background Search**: Comprehensive search for analytics
3. **Cache Results**: Store user positions to reduce future searches
4. **Pagination Required**: Use `cursorAfter`/`cursorBefore` for efficient traversal
## Best Practices
1. **Pagination**: Use cursor-based pagination (`cursorAfter`/`cursorBefore`)
2. **Rate Limiting**: Add 200-500ms delays between pagination requests
3. **Caching**: Cache leaderboard data for 30-60 seconds
4. **Search Limits**: Limit user searches to reasonable page counts (50-100 pages)
5. **Sprint Context**: Use `sprintId` for time-limited competitions
## Common Errors
| Error | Cause | Solution |
| --------------------- | -------------------- | --------------------------------- |
| `Space not found` | Invalid space ID | Verify space ID exists |
| `Invalid sprint ID` | Sprint doesn't exist | Check sprint ID or omit parameter |
| `Rate limit exceeded` | Too many requests | Implement retry logic |
| `Invalid cursor` | Malformed cursor | Start fresh without cursor |
## Next Steps
* **[Loyalty Program Guide](/galxe-integration/guides/loyalty-program)** - Points implementation
* **[Leaderboard Guide](/galxe-integration/guides/leaderboards)** - Advanced ranking features
* **[Authentication](/galxe-integration/getting-started/authentication)** - Access token setup
# Starboard API Reference
Source: https://docs.galxe.com/galxe-integration/api-reference/starboard
Track Twitter influence rankings and social metrics
## Overview
The Starboard API provides access to Twitter influence rankings, social metrics, and engagement analytics.
## Core Queries
### Get Starboard Information
```graphql theme={null}
query GetStarboard($id: ID!) {
starboard(id: $id) {
basicInfo {
id
name
projectName
description
tags
type
reward {
name
description
startTime
endTime
}
}
}
}
```
### Get Starboard Leaderboard
```graphql theme={null}
query GetStarboardLeaderboard($id: ID!, $first: Int!, $after: String) {
starboard(id: $id) {
leaderboard(
pagination: {
forward: {
first: $first
after: $after
}
}
) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
xUserProfile {
username
followersCount
verifiedType
}
rank {
value
delta
deltaRate
}
influenceScore {
value
delta
deltaRate
}
change24H { value deltaRate }
change7D { value deltaRate }
change30D { value deltaRate }
}
}
}
}
}
```
### Search Specific User
```graphql theme={null}
query SearchUser($id: ID!, $twitterId: String!) {
starboard(id: $id) {
leaderboard(
twitterId: $twitterId
pagination: { forward: { first: 1 } }
) {
edges {
node {
rank { value }
influenceScore { value deltaRate }
xUserProfile {
username
followersCount
verifiedType
}
}
}
}
}
}
```
**Variables**:
```json theme={null}
{
"id": "1",
"twitterId": "elonmusk"
}
```
### Get Twitter Handle by EVM Address
```graphql theme={null}
query GetTwitterHandleByEvmAddress($id: ID!, $evmAddress: String!) {
starboard(id: $id) {
twitterHandleByEvmAddress(evmAddress: $evmAddress) {
evmAddress
mainAddress
twitterHandle
isPublic
}
}
}
```
**Variables**:
```json theme={null}
{
"id": "1",
"evmAddress": "0x1234567890abcdef1234567890abcdef12345678"
}
```
### Get User Detail
```graphql theme={null}
query GetUserDetail($id: ID!, $evmAddress: String!) {
starboard(id: $id) {
userDetail(evmAddress: $evmAddress) {
starboardId
twitterHandle
individual
aura
isPublic
}
}
}
```
**Variables**:
```json theme={null}
{
"id": "1",
"evmAddress": "0x1234567890abcdef1234567890abcdef12345678"
}
```
## Field Reference
### Starboard Types
| Type | Description |
| --------- | -------------------------- |
| `TWITTER` | Twitter influence tracking |
| `ONCHAIN` | On-chain activity tracking |
### Verification Types
| Type | Description |
| ------------ | ------------------------------- |
| `blue` | Twitter Blue verification |
| `business` | Business account verification |
| `government` | Government account verification |
| `none` | No verification |
### StarboardMetricValue Structure
All metrics include comprehensive tracking data:
| Field | Type | Description |
| ------------ | --------- | ------------------------------------ |
| `value` | `String!` | Current metric value |
| `delta` | `Int!` | Absolute change from previous period |
| `deltaRate` | `Float!` | Percentage change rate |
| `percentage` | `Float!` | Relative percentage score |
### Key Fields
| Field | Type | Description |
| --------------------------- | --------------------------- | ------------------------------------- |
| `basicInfo` | `StarboardBasicInfo!` | Starboard metadata |
| `leaderboard` | `StarboardLeaderboard` | Rankings and metrics |
| `xUserProfile` | `XUserProfile` | Twitter user information |
| `rank` | `StarboardMetricValue` | User's ranking position |
| `influenceScore` | `StarboardMetricValue` | User's influence score |
| `twitterHandleByEvmAddress` | `TwitterHandleByEvmAddress` | Twitter handle lookup by EVM address |
| `userDetail` | `StarboardUserDetail` | Detailed user metrics for EVM address |
### TwitterHandleByEvmAddress Type
| Field | Type | Description |
| --------------- | ---------- | -------------------------------- |
| `evmAddress` | `String!` | The queried EVM address |
| `mainAddress` | `String!` | The main associated address |
| `twitterHandle` | `String!` | Twitter username for the address |
| `isPublic` | `Boolean!` | Whether the profile is public |
### StarboardUserDetail Type
| Field | Type | Description |
| --------------- | ---------- | ----------------------------- |
| `starboardId` | `String!` | The starboard identifier |
| `twitterHandle` | `String!` | Twitter username |
| `individual` | `Int!` | Individual score metric |
| `aura` | `Int!` | Aura score metric |
| `isPublic` | `Boolean!` | Whether the profile is public |
## Integration Patterns
### Basic Leaderboard Query
```bash theme={null}
curl -X POST https://graphigo-business.prd.galaxy.eco/query \
-H "Content-Type: application/json" \
-H "access-token: YOUR_ACCESS_TOKEN" \
-d '{
"query": "query GetStarboard($id: ID!) { starboard(id: $id) { basicInfo { name type } leaderboard(pagination: { forward: { first: 10 } }) { edges { node { rank { value } xUserProfile { username followersCount } } } } } }",
"variables": { "id": "1" }
}'
```
### Pagination Pattern
Starboards use nested pagination structure:
```json theme={null}
{
"pagination": {
"forward": {
"first": 20,
"after": "cursor_value"
}
}
}
```
### User Search
To find a specific Twitter user, use the `twitterId` parameter with their Twitter username.
### Trend Analysis
Use the change metrics to analyze user performance:
* `change24H` - 24-hour trends
* `change7D` - 7-day trends
* `change30D` - 30-day trends
Each includes `value` (current metric) and `deltaRate` (percentage change).
## Best Practices
1. **Rate Limiting**: Limit monitoring requests to once every 5 minutes
2. **Pagination**: Use forward pagination for efficient data retrieval
3. **Caching**: Cache influence data for 60-300 seconds
4. **Error Handling**: Handle cases where users are not tracked
5. **Trend Monitoring**: Set alerts for significant score changes (±10%)
6. **User Verification**: Check `verifiedType` for account authenticity
## Common Errors
| Error | Cause | Solution |
| ------------------------ | -------------------------- | ------------------------------------ |
| `Starboard not found` | Invalid starboard ID | Verify starboard ID exists |
| `Twitter user not found` | User not tracked | Check if user is in starboard |
| `Invalid pagination` | Malformed pagination input | Use proper PaginationInput structure |
| `Rate limit exceeded` | Too many requests | Implement retry logic |
## Next Steps
* **[Starboard Integration Guide](/galxe-integration/guides/starboards)** - Complete implementation patterns
* **[Authentication](/galxe-integration/getting-started/authentication)** - Access token setup
* **[Common Patterns](/galxe-integration/getting-started/common-patterns)** - Reusable patterns
# Authentication
Source: https://docs.galxe.com/galxe-integration/getting-started/authentication
All Galxe API requests require a valid access token for authentication
## Get Your Access Token
1. **Login to Galxe** - Visit [dashboard.galxe.com](https://dashboard.galxe.com/)
2. **Open Settings** - Click your Account → Settings
3. **API Access** - Navigate to "Server API" section
4. **Generate Token** - Click "Generate New API Tokens"
5. **Copy Token** - Save the token securely (you can't view it again)
## Using the Token
Include your token in the `access-token` header:
```bash theme={null}
curl -X POST https://graphigo-business.prd.galaxy.eco/query \
-H "Content-Type: application/json" \
-H "access-token: YOUR_ACCESS_TOKEN" \
-d '{"query": "query { __typename }"}'
```
## Security Best Practices
### Environment Variables
```bash theme={null}
# .env file
GALXE_ACCESS_TOKEN=your_token_here
```
```javascript theme={null}
// JavaScript
const accessToken = process.env.GALXE_ACCESS_TOKEN;
```
```python theme={null}
# Python
import os
access_token = os.getenv('GALXE_ACCESS_TOKEN')
```
### Production Deployment
* Use secret management systems (AWS Secrets Manager, HashiCorp Vault)
* Never commit tokens to version control
* Rotate tokens regularly
* Use environment-specific tokens
## Common Issues
### Invalid Token
```json theme={null}
{
"errors": [{
"message": "Invalid access token: invalid token",
"extensions": {
"code": "INVALID_TOKEN",
"category": "AUTHENTICATION",
"http_status": 401,
"request_id": "req_123456789",
"timestamp": "2024-01-01T00:00:00Z"
}
}]
}
```
**Solution**: Regenerate token in dashboard settings
### Missing Header
```json theme={null}
{
"errors": [{
"message": "Access token is required",
"extensions": {
"code": "TOKEN_REQUIRED",
"category": "AUTHENTICATION",
"http_status": 401,
"request_id": "req_123456789",
"timestamp": "2024-01-01T00:00:00Z"
}
}]
}
```
**Solution**: Add `access-token` header to request
### Rate Limiting
```json theme={null}
{
"errors": [{
"message": "API quota exceeded: daily limit reached",
"extensions": {
"code": "QUOTA_EXCEEDED",
"category": "RATE_LIMIT",
"http_status": 429,
"request_id": "req_123456789",
"timestamp": "2024-01-01T00:00:00Z",
"details": ["quota_type: daily", "limit: 1000"]
}
}]
}
```
**Solution**: Implement exponential backoff retry logic
## Error Response Format
All GraphQL errors follow a standardized format with additional metadata:
```json theme={null}
{
"errors": [{
"message": "Human-readable error message",
"extensions": {
"code": "ERROR_CODE", // Machine-readable error code
"category": "ERROR_CATEGORY", // Error classification
"http_status": 400, // Corresponding HTTP status
"request_id": "req_xxx", // Request tracking ID
"timestamp": "2024-01-01T00:00:00Z",
"details": ["additional", "context"], // Optional details array
"context": { // Optional context object
"field": "value"
}
}
}]
}
```
### Error Codes and Categories
| Code | Category | HTTP Status | Description |
| ------------------- | ---------------- | ----------- | ------------------------ |
| `TOKEN_REQUIRED` | `AUTHENTICATION` | 401 | Access token missing |
| `INVALID_TOKEN` | `AUTHENTICATION` | 401 | Access token invalid |
| `QUOTA_EXCEEDED` | `RATE_LIMIT` | 429 | API quota exceeded |
| `PERMISSION_DENIED` | `AUTHORIZATION` | 403 | Insufficient permissions |
| `NOT_FOUND` | `NOT_FOUND` | 404 | Resource not found |
| `INVALID_ARGUMENT` | `VALIDATION` | 400 | Invalid input parameters |
## Next Steps
* **[Quick Start](/galxe-integration/getting-started/quick-start)** - Test your token
* **[Common Patterns](/galxe-integration/getting-started/common-patterns)** - Integration patterns
* **[Rate Limits](/galxe-integration/resources/rate-limits)** - API limits and optimization
# Common Integration Patterns
Source: https://docs.galxe.com/galxe-integration/getting-started/common-patterns
Reusable code patterns and GraphQL queries for efficient Galxe integration
## Authentication & Setup
### Basic GraphQL Client
```javascript theme={null}
const executeQuery = async (query, variables = {}) => {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': process.env.GALXE_ACCESS_TOKEN
},
body: JSON.stringify({ query, variables })
});
const data = await response.json();
if (data.errors) throw new Error(data.errors[0].message);
return data.data;
};
```
### Error Handling with Retry
```javascript theme={null}
const retryQuery = async (query, variables, maxRetries = 3) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await executeQuery(query, variables);
} catch (error) {
const isRetryable = error.message.includes('rate limit') ||
error.message.includes('timeout');
if (isRetryable && attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
continue;
}
throw error;
}
}
};
```
## Quest Patterns
### Quest Status Validation
```graphql theme={null}
query QuestStatus($id: ID!) {
quest(id: $id) {
status
startTime
endTime
}
}
```
```javascript theme={null}
const isQuestActive = (quest) => {
const now = Date.now() / 1000;
return quest.status === 'Active' &&
now >= quest.startTime &&
now <= quest.endTime;
};
const getQuestPhase = (quest) => {
const now = Date.now() / 1000;
if (now < quest.startTime) return 'upcoming';
if (now <= quest.endTime) return 'active';
return 'ended';
};
```
### User Eligibility Check
```graphql theme={null}
query CheckEligibility($questId: ID!, $address: String!) {
quest(id: $questId) {
credentialGroups(address: $address) {
conditions { eligible }
rewards { eligible rewardType }
}
}
}
```
```javascript theme={null}
const checkEligibility = async (questId, address) => {
const data = await executeQuery(`
query CheckEligibility($questId: ID!, $address: String!) {
quest(id: $questId) {
credentialGroups(address: $address) {
conditions { eligible }
rewards { eligible }
}
}
}
`, { questId, address });
return data.quest.credentialGroups.some(group =>
group.conditions.some(c => c.eligible) &&
group.rewards.some(r => r.eligible)
);
};
```
## Pagination Patterns
### Standard Pagination Query
```graphql theme={null}
query PaginatedQuery($first: Int!, $after: String) {
items(first: $first, after: $after) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
# your fields here
}
}
}
}
```
### Fetch All Pages
```javascript theme={null}
const fetchAllPages = async (query, variables = {}, extractPath) => {
let allItems = [];
let hasNextPage = true;
let cursor = null;
while (hasNextPage) {
const data = await executeQuery(query, {
...variables,
first: 100,
after: cursor
});
const result = extractPath(data);
allItems.push(...result.edges.map(edge => edge.node));
hasNextPage = result.pageInfo.hasNextPage;
cursor = result.pageInfo.endCursor;
// Rate limiting
await new Promise(resolve => setTimeout(resolve, 100));
}
return allItems;
};
// Usage example
const allQuests = await fetchAllPages(
`query GetQuests($spaceId: ID!, $first: Int!, $after: String) {
quests(input: {spaceId: $spaceId, first: $first, after: $after}) {
pageInfo { hasNextPage endCursor }
list { id name status }
}
}`,
{ spaceId: "40" },
data => data.quests
);
```
## Leaderboard Patterns
### User Position Search
**No Direct User Lookup**: The B2B API does not provide direct user position lookup. You must search through leaderboard pages to find a specific user.
```javascript theme={null}
const findUserPosition = async (spaceId, userAddress) => {
let cursorAfter = null;
let pageCount = 0;
const maxPages = 20; // Reasonable search limit
while (pageCount < maxPages) {
const data = await executeQuery(`
query SearchUser($spaceId: Int!, $cursorAfter: String) {
space(id: $spaceId) {
loyaltyPointsRanks(cursorAfter: $cursorAfter) {
pageInfo { hasNextPage endCursor }
list {
rank
points
address { address username }
}
}
}
}
`, { spaceId, cursorAfter });
const userRank = data.space.loyaltyPointsRanks.list.find(item =>
item.address.address.toLowerCase() === userAddress.toLowerCase()
);
if (userRank) {
return { found: true, rank: userRank.rank, points: userRank.points };
}
if (!data.space.loyaltyPointsRanks.pageInfo.hasNextPage) break;
cursorAfter = data.space.loyaltyPointsRanks.pageInfo.endCursor;
pageCount++;
await new Promise(resolve => setTimeout(resolve, 100)); // Rate limiting
}
return { found: false, rank: null, points: 0 };
};
const getLeaderboardWithUser = async (spaceId, userAddress) => {
const [leaderboardData, userPosition] = await Promise.all([
executeQuery(`
query GetLeaderboard($spaceId: Int!) {
space(id: $spaceId) {
loyaltyPointsRanks(first: 10) {
list {
rank
points
address { username }
}
}
}
}
`, { spaceId }),
findUserPosition(spaceId, userAddress)
]);
return {
leaderboard: leaderboardData.space.loyaltyPointsRanks.list,
userPosition
};
};
```
## Credential Patterns
### Batch Eligibility Check
```javascript theme={null}
const checkBatchEligibility = async (credId, addresses) => {
const promises = addresses.map(address =>
executeQuery(`
query CheckEligibility($credId: ID!, $address: String!) {
credential(id: $credId) { eligible(address: $address) }
}
`, { credId, address })
.then(data => ({ address, eligible: data.credential.eligible === 1 }))
.catch(() => ({ address, eligible: false }))
);
return Promise.all(promises);
};
```
### Credential Validation
```javascript theme={null}
const validateCredential = async (credId) => {
const data = await executeQuery(`
query ValidateCredential($credId: ID!) {
credential(id: $credId) {
syncStatus
itemCount
lastUpdate
}
}
`, { credId });
const cred = data.credential;
return {
isValid: cred.syncStatus === 'SYNCED',
hasHolders: cred.itemCount > 0,
lastSynced: new Date(cred.lastUpdate * 1000)
};
};
```
## Real-time Monitoring
### Simple Polling Monitor
```javascript theme={null}
const createMonitor = (queryFn, interval = 30000) => {
let intervalId = null;
const start = (callback) => {
intervalId = setInterval(async () => {
try {
const data = await queryFn();
callback({ type: 'update', data });
} catch (error) {
callback({ type: 'error', error: error.message });
}
}, interval);
};
const stop = () => {
if (intervalId) {
clearInterval(intervalId);
intervalId = null;
}
};
return { start, stop };
};
// Usage
const leaderboardMonitor = createMonitor(
() => getLeaderboardWithUser(40, userAddress),
60000 // 1 minute
);
leaderboardMonitor.start((update) => {
if (update.type === 'update') {
console.log('Leaderboard updated:', update.data);
}
});
```
## Rate Limiting
### Simple Rate Limiter
```javascript theme={null}
class RateLimiter {
constructor(requestsPerSecond = 10) {
this.requests = [];
this.maxRequests = requestsPerSecond;
}
async execute(fn) {
const now = Date.now();
this.requests = this.requests.filter(time => now - time < 1000);
if (this.requests.length >= this.maxRequests) {
const waitTime = 1000 - (now - this.requests[0]);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
this.requests.push(now);
return fn();
}
}
// Usage
const limiter = new RateLimiter(5); // 5 requests per second
const data = await limiter.execute(() =>
executeQuery(query, variables)
);
```
## Data Transformation
### Standardize User Objects
```javascript theme={null}
const standardizeUser = (userObject) => {
// Handle different user object formats
if (userObject.address) {
return {
id: userObject.address.id || userObject.address.address,
username: userObject.address.username,
address: userObject.address.address
};
}
return {
id: userObject.id,
username: userObject.username,
address: userObject.address
};
};
```
### Format Points and Rankings
```javascript theme={null}
const formatRanking = (rankingData) => ({
rank: parseInt(rankingData.rank),
points: parseInt(rankingData.points),
user: standardizeUser(rankingData),
rankMovement: rankingData.delta || 0
});
const formatLeaderboard = (leaderboardData) => ({
totalCount: leaderboardData.totalCount,
rankings: leaderboardData.edges.map(edge => formatRanking(edge.node)),
hasNextPage: leaderboardData.pageInfo.hasNextPage
});
```
## Utility Functions
### Time Helpers
```javascript theme={null}
const timeHelpers = {
toUnix: (date) => Math.floor(date.getTime() / 1000),
fromUnix: (timestamp) => new Date(timestamp * 1000),
isAfter: (timestamp) => Date.now() / 1000 > timestamp,
formatDuration: (seconds) => {
const days = Math.floor(seconds / 86400);
const hours = Math.floor((seconds % 86400) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return `${days}d ${hours}h ${minutes}m`;
}
};
```
### Validation Helpers
```javascript theme={null}
const validators = {
isValidAddress: (address) => /^0x[a-fA-F0-9]{40}$/.test(address),
isValidQuestId: (id) => typeof id === 'string' && id.length > 0,
isValidSpaceId: (id) => Number.isInteger(id) && id > 0
};
```
## Best Practices Summary
1. **Always validate inputs** before API calls
2. **Implement retry logic** for network failures
3. **Use pagination** for large datasets
4. **Cache frequently accessed data** (30-60 seconds)
5. **Handle rate limits** with exponential backoff
6. **Monitor for errors** and log appropriately
7. **Use environment variables** for sensitive data
## Quick Reference
### Essential Queries
* Quest status: `quest(id) { status startTime endTime }`
* User eligibility: `quest(id) { credentialGroups(address) { conditions { eligible } } }`
* Leaderboard: `space(id) { loyaltyPointsRanks(cursorAfter) { list { rank points address { username } } } }`
* User search: Must paginate through leaderboard to find specific users
### Common Response Patterns
* Paginated: `{ pageInfo { hasNextPage endCursor } edges { node { ... } } }`
* User objects: `{ address { username address } }` or `{ username address }`
* Error format: `{ errors [{ message extensions { code category } }] }`
## Next Steps
* **[Quest Guide](/galxe-integration/guides/quests)** - Complete quest implementation
* **[Leaderboard Guide](/galxe-integration/guides/leaderboards)** - Advanced ranking features
* **[API Reference](/galxe-integration/api-reference/quest)** - Detailed API documentation
# Quick Start
Source: https://docs.galxe.com/galxe-integration/getting-started/quick-start
Get your first API call working in under 3 minutes
## Step 1: Get Access Token
1. Visit [Galxe Dashboard Settings](https://dashboard.galxe.com)
2. Navigate to "Server API" section
3. Click "Generate New API Tokens"
4. Copy the token (save it securely - you can't view it again)
## Step 2: Test Basic Connection
```bash theme={null}
curl -X POST https://graphigo-business.prd.galaxy.eco/query \
-H "Content-Type: application/json" \
-H "access-token: YOUR_ACCESS_TOKEN" \
-d '{"query": "query { __typename }"}'
```
**Expected Response:**
```json theme={null}
{"data": {"__typename": "Query"}}
```
If you see this response, your token is working correctly!
## Step 3: Try Your First Real Query
### Get Quest Information
```bash theme={null}
curl -X POST https://graphigo-business.prd.galaxy.eco/query \
-H "Content-Type: application/json" \
-H "access-token: YOUR_ACCESS_TOKEN" \
-d '{
"query": "query GetQuest($id: ID!) { quest(id: $id) { name status participantsCount } }",
"variables": { "id": "GChdWUjXX3" }
}'
```
**Expected Response:**
```json theme={null}
{
"data": {
"quest": {
"name": "Introduction to Web3!",
"status": "Active",
"participantsCount": 234163
}
}
}
```
## What's Next?
Secure token setup and best practices
Ready-to-use code snippets
Complete quest implementation
Detailed API documentation
## Need Help?
* **Discord**: [Join our community](https://discord.gg/galxe)
* **Support**: [support@galxe.com](mailto:support@galxe.com)
* **Documentation**: Continue with [Authentication Setup](/galxe-integration/getting-started/authentication)
# Leaderboard Integration
Source: https://docs.galxe.com/galxe-integration/guides/leaderboards
Create engaging leaderboard systems with real-time rankings and user analytics
## Overview
Build leaderboard systems that drive engagement through:
* Real-time user rankings via loyalty points
* Paginated leaderboard data with cursor-based pagination
* Sprint-specific leaderboards for competitions
* Space-level ranking analytics
## Basic Leaderboard Query
### Get Leaderboard Rankings
```graphql theme={null}
query GetLeaderboard($spaceId: Int!, $cursorAfter: String, $sprintId: Int) {
space(id: $spaceId) {
id
name
loyaltyPointsRanks(
cursorAfter: $cursorAfter
sprintId: $sprintId
) {
totalCount
pageInfo {
hasNextPage
endCursor
}
list {
rank
points
address {
username
avatar
address
}
}
}
}
}
```
**Variables**:
```json theme={null}
{
"spaceId": 40,
"cursorAfter": null,
"sprintId": null
}
```
**Response**:
```json theme={null}
{
"data": {
"space": {
"id": "40",
"name": "BNB Chain",
"loyaltyPointsRanks": {
"totalCount": 1500,
"pageInfo": {
"hasNextPage": true,
"endCursor": "cursor_end"
},
"list": [
{
"rank": 1,
"points": 5000,
"address": {
"username": "TopPlayer",
"avatar": "https://example.com/avatar.jpg",
"address": "0x1234567890123456789012345678901234567890"
}
}
]
}
}
}
}
```
## Sprint-Specific Leaderboards
### Get Sprint Rankings
When you have a sprint ID, get sprint-specific rankings:
```graphql theme={null}
query GetSprintLeaderboard($spaceId: Int!, $sprintId: Int!, $cursorAfter: String) {
space(id: $spaceId) {
loyaltyPointsRanks(
sprintId: $sprintId
cursorAfter: $cursorAfter
) {
totalCount
list {
rank
points
address {
username
address
}
}
}
}
}
```
**Sprint Management**: Sprint information must come from external sources as sprint management is not available through this API.
## Pagination Patterns
### Cursor-Based Navigation
```bash theme={null}
# Get first page
curl -X POST https://graphigo-business.prd.galaxy.eco/query \
-H "Content-Type: application/json" \
-H "access-token: YOUR_ACCESS_TOKEN" \
-d '{
"query": "query GetLeaderboard($spaceId: Int!) { space(id: $spaceId) { loyaltyPointsRanks(cursorAfter: null) { totalCount pageInfo { hasNextPage endCursor } list { rank points address { username } } } } }",
"variables": { "spaceId": 40 }
}'
```
### Loading Next Page
1. Use `pageInfo.endCursor` from previous response
2. Set as `cursorAfter` parameter for next request
3. Continue until `pageInfo.hasNextPage` is `false`
## User Position Lookup
**No Direct User Lookup**: To find a specific user's rank, you must paginate through the leaderboard.
### Search Strategy
Since there's no direct user lookup, implement efficient search:
1. **Limited Search**: Search first 10-20 pages for UI responsiveness
2. **Background Search**: Comprehensive search for analytics
3. **Caching**: Store user positions to reduce future searches
### Basic Implementation
```javascript theme={null}
async function findUserPosition(spaceId, userAddress, accessToken) {
let cursorAfter = null;
let pageCount = 0;
const maxPages = 20; // UI-friendly limit
while (pageCount < maxPages) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetLeaderboard($spaceId: Int!, $cursorAfter: String) {
space(id: $spaceId) {
loyaltyPointsRanks(cursorAfter: $cursorAfter) {
pageInfo { hasNextPage endCursor }
list { rank points address { address username } }
}
}
}`,
variables: { spaceId, cursorAfter }
})
});
const data = await response.json();
const ranks = data.data.space.loyaltyPointsRanks;
// Search current page
const userRank = ranks.list.find(item =>
item.address.address.toLowerCase() === userAddress.toLowerCase()
);
if (userRank) {
return {
found: true,
rank: userRank.rank,
points: userRank.points,
username: userRank.address.username,
searchPages: pageCount + 1
};
}
if (!ranks.pageInfo.hasNextPage) break;
cursorAfter = ranks.pageInfo.endCursor;
pageCount++;
// Rate limiting
await new Promise(resolve => setTimeout(resolve, 100));
}
return { found: false, searchPages: pageCount };
}
```
## Common Integration Patterns
### Top N Rankings
```javascript theme={null}
// Get top 10 users
async function getTopRankings(spaceId, count = 10, accessToken) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetTopRankings($spaceId: Int!) {
space(id: $spaceId) {
name
loyaltyPointsRanks(cursorAfter: null) {
totalCount
list { rank points address { username avatar } }
}
}
}`,
variables: { spaceId }
})
});
const data = await response.json();
const leaderboard = data.data.space.loyaltyPointsRanks;
return {
spaceName: data.data.space.name,
totalParticipants: leaderboard.totalCount,
topUsers: leaderboard.list.slice(0, count)
};
}
```
### Sprint vs Overall Comparison
```javascript theme={null}
async function compareRankings(spaceId, sprintId, accessToken) {
const [overall, sprint] = await Promise.all([
getTopRankings(spaceId, 10, accessToken),
getSprintRankings(spaceId, sprintId, 10, accessToken)
]);
return {
overall: overall.topUsers,
sprint: sprint.topUsers,
comparison: {
overallParticipants: overall.totalParticipants,
sprintParticipants: sprint.totalParticipants,
participationRate: sprint.totalParticipants / overall.totalParticipants
}
};
}
async function getSprintRankings(spaceId, sprintId, count, accessToken) {
// Similar to getTopRankings but with sprintId parameter
// Implementation details follow the same pattern
}
```
## Best Practices
1. **Pagination**: Use cursor-based pagination (`cursorAfter`/`cursorBefore`)
2. **Rate Limiting**: Add 200-500ms delays between pagination requests
3. **Caching**: Cache leaderboard data for 30-60 seconds
4. **Search Limits**: Limit user searches to reasonable page counts (20-50 pages)
5. **Error Handling**: Handle cases where users are not found in rankings
6. **Sprint Context**: Use `sprintId` for time-limited competitions
## Pagination Parameters
### Current (Recommended)
* `cursorAfter`: Get items after this cursor
* `cursorBefore`: Get items before this cursor
* `sprintId`: Optional sprint ID for sprint-specific rankings
### Deprecated (Avoid)
* `first`: Use cursor-based pagination instead
* `after`: Use cursor-based pagination instead
## Limitations & Workarounds
### Current Limitations
1. **No Direct User Lookup**: Must search through pages
2. **No Sprint Management**: Sprint IDs from external sources
3. **Search Performance**: Finding users requires multiple API calls
### Recommended Workarounds
1. **Efficient Search**: Limit search scope for UI responsiveness
2. **Caching Strategy**: Cache user positions for short periods
3. **User Communication**: Set expectations about search time
4. **Fallback UI**: Show leaderboard context even when user isn't found
## Usage Examples
### Basic Leaderboard Display
```javascript theme={null}
// Get and display top 10 rankings
const topRankings = await getTopRankings(40, 10, accessToken);
console.log(`${topRankings.spaceName} Leaderboard`);
console.log(`Total participants: ${topRankings.totalParticipants}`);
console.log('\nTop 10:');
topRankings.topUsers.forEach(user => {
console.log(`${user.rank}. ${user.address.username} - ${user.points} points`);
});
```
### User Position Check
```javascript theme={null}
// Find specific user's position
const userAddress = '0x1234567890123456789012345678901234567890';
const position = await findUserPosition(40, userAddress, accessToken);
if (position.found) {
console.log(`User rank: #${position.rank}`);
console.log(`User points: ${position.points}`);
console.log(`Search completed in ${position.searchPages} pages`);
} else {
console.log(`User not found in top ${position.searchPages * 50} participants`);
}
```
## Next Steps
* **[Space API Reference](/galxe-integration/api-reference/space)** - Complete API documentation
* **[Loyalty Program Guide](/galxe-integration/guides/loyalty-program)** - Points and rewards system
* **[Authentication](/galxe-integration/getting-started/authentication)** - Access token setup
# Loyalty Program Integration
Source: https://docs.galxe.com/galxe-integration/guides/loyalty-program
Create engaging loyalty programs with point systems and leaderboard analytics
## Overview
Build loyalty programs that reward user engagement through:
* Quest-based point accumulation
* Leaderboard-driven competition
* User progress tracking via rankings
* Sprint-specific campaigns
## Understanding Loyalty Points
### Quest Points System
Each quest can award loyalty points to participants:
```graphql theme={null}
query GetQuestPoints($questId: ID!) {
quest(id: $questId) {
id
name
loyaltyPoints
status
space {
id
name
}
}
}
```
**Response**:
```json theme={null}
{
"data": {
"quest": {
"id": "GChdWUjXX3",
"name": "Introduction to Web3!",
"loyaltyPoints": 100,
"status": "Active",
"space": {
"id": "40",
"name": "BNB Chain"
}
}
}
}
```
### Get User Points via Leaderboard
```graphql theme={null}
query GetLeaderboard($spaceId: Int!, $cursorAfter: String) {
space(id: $spaceId) {
id
name
loyaltyPointsRanks(cursorAfter: $cursorAfter) {
totalCount
pageInfo {
hasNextPage
endCursor
}
list {
rank
points
address {
username
avatar
address
}
}
}
}
}
```
## Basic Implementation
### Find User Points
```javascript theme={null}
async function findUserPoints(spaceId, userAddress, accessToken) {
let cursorAfter = null;
let pageCount = 0;
const maxPages = 20; // Reasonable search limit
while (pageCount < maxPages) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetLeaderboard($spaceId: Int!, $cursorAfter: String) {
space(id: $spaceId) {
loyaltyPointsRanks(cursorAfter: $cursorAfter) {
totalCount
pageInfo { hasNextPage endCursor }
list {
rank
points
address { address username avatar }
}
}
}
}`,
variables: { spaceId, cursorAfter }
})
});
const data = await response.json();
const ranks = data.data.space.loyaltyPointsRanks;
// Search current page
const userRank = ranks.list.find(item =>
item.address.address.toLowerCase() === userAddress.toLowerCase()
);
if (userRank) {
return {
found: true,
points: userRank.points,
rank: userRank.rank,
username: userRank.address.username,
totalParticipants: ranks.totalCount,
searchPages: pageCount + 1
};
}
if (!ranks.pageInfo.hasNextPage) break;
cursorAfter = ranks.pageInfo.endCursor;
pageCount++;
// Rate limiting
await new Promise(resolve => setTimeout(resolve, 100));
}
return {
found: false,
points: 0,
rank: null,
totalParticipants: pageCount > 0 ? ranks.totalCount : 0,
searchPages: pageCount
};
}
```
### Get Quest Points Information
```javascript theme={null}
async function getQuestPointValue(questId, accessToken) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetQuestPoints($questId: ID!) {
quest(id: $questId) {
id
name
loyaltyPoints
status
space { id name }
}
}`,
variables: { questId }
})
});
const data = await response.json();
return data.data.quest;
}
```
## Sprint-Based Programs
### Sprint vs Overall Comparison
```graphql theme={null}
query GetSprintLeaderboard($spaceId: Int!, $sprintId: Int!, $cursorAfter: String) {
space(id: $spaceId) {
loyaltyPointsRanks(
sprintId: $sprintId
cursorAfter: $cursorAfter
) {
totalCount
list {
rank
points
address {
username
address
}
}
}
}
}
```
**Sprint Management**: Sprint information must come from external sources as sprint management is not available through this API.
### Compare User Progress
```javascript theme={null}
async function compareUserProgress(spaceId, userAddress, sprintId, accessToken) {
const [overall, sprint] = await Promise.all([
findUserPoints(spaceId, userAddress, accessToken),
findUserPointsInSprint(spaceId, userAddress, sprintId, accessToken)
]);
return {
overall: {
points: overall.points,
rank: overall.rank,
found: overall.found
},
sprint: {
points: sprint.points,
rank: sprint.rank,
found: sprint.found,
sprintId
},
comparison: {
pointsDifference: sprint.points - overall.points,
rankImprovement: overall.rank && sprint.rank
? overall.rank - sprint.rank
: null,
sprintPerformance: sprint.rank && overall.rank
? sprint.rank < overall.rank ? 'better' : 'worse'
: 'unknown'
}
};
}
// Similar to findUserPoints but with sprintId parameter
async function findUserPointsInSprint(spaceId, userAddress, sprintId, accessToken) {
// Implementation follows same pattern as findUserPoints
// but includes sprintId in the loyaltyPointsRanks query
}
```
## User Dashboard Pattern
### Create User Dashboard
```javascript theme={null}
async function createUserDashboard(spaceId, userAddress, accessToken) {
const userData = await findUserPoints(spaceId, userAddress, accessToken);
if (!userData.found) {
return {
user: {
address: userAddress,
points: 0,
rank: null,
isRanked: false,
message: 'User not found in top rankings'
},
leaderboard: {
totalParticipants: userData.totalParticipants,
searchedPages: userData.searchPages
}
};
}
// Calculate percentile
const percentile = userData.totalParticipants
? ((userData.totalParticipants - userData.rank) / userData.totalParticipants) * 100
: 0;
return {
user: {
address: userAddress,
username: userData.username,
points: userData.points,
rank: userData.rank,
isRanked: true,
percentile: Math.round(percentile)
},
leaderboard: {
totalParticipants: userData.totalParticipants,
searchedPages: userData.searchPages
},
spaceInfo: {
id: spaceId
}
};
}
```
## Quest Integration
### Track Quest Completion
```javascript theme={null}
async function trackQuestCompletion(questId, userAddress, accessToken) {
const quest = await getQuestPointValue(questId, accessToken);
if (!quest) {
return { error: 'Quest not found' };
}
if (quest.loyaltyPoints === 0) {
return { message: 'Quest does not award loyalty points' };
}
const userPoints = await findUserPoints(
parseInt(quest.space.id),
userAddress,
accessToken
);
return {
quest: {
id: quest.id,
name: quest.name,
points: quest.loyaltyPoints,
status: quest.status,
space: quest.space
},
user: {
currentPoints: userPoints.points,
currentRank: userPoints.rank,
projectedPoints: userPoints.points + quest.loyaltyPoints,
isCurrentlyRanked: userPoints.found
},
impact: {
pointsGain: quest.loyaltyPoints
}
};
}
```
## Common Integration Patterns
### Points-Based Access Control
```javascript theme={null}
async function checkPointsRequirement(spaceId, userAddress, requiredPoints, accessToken) {
const userPoints = await findUserPoints(spaceId, userAddress, accessToken);
return {
hasAccess: userPoints.points >= requiredPoints,
userPoints: userPoints.points,
requiredPoints,
deficit: Math.max(0, requiredPoints - userPoints.points),
rank: userPoints.rank,
isRanked: userPoints.found
};
}
```
### Achievement Thresholds
```javascript theme={null}
function calculateAchievements(userPoints) {
const thresholds = [
{ name: 'Newcomer', points: 10 },
{ name: 'Explorer', points: 100 },
{ name: 'Adventurer', points: 500 },
{ name: 'Champion', points: 1000 },
{ name: 'Legend', points: 5000 }
];
const achieved = thresholds.filter(t => userPoints >= t.points);
const nextThreshold = thresholds.find(t => userPoints < t.points);
return {
current: achieved[achieved.length - 1] || { name: 'Beginner', points: 0 },
next: nextThreshold,
progress: nextThreshold
? (userPoints - achieved[achieved.length - 1]?.points || 0) / (nextThreshold.points - (achieved[achieved.length - 1]?.points || 0))
: 1,
totalAchieved: achieved.length
};
}
```
## Usage Examples
### Basic User Profile
```javascript theme={null}
// Get user loyalty program status
const accessToken = process.env.GALXE_ACCESS_TOKEN;
const spaceId = 40; // BNB Chain space
const userAddress = '0x1234567890123456789012345678901234567890';
const dashboard = await createUserDashboard(spaceId, userAddress, accessToken);
console.log('User Points:', dashboard.user.points);
console.log('User Rank:', dashboard.user.rank);
console.log('Percentile:', dashboard.user.percentile + '%');
console.log('Total Participants:', dashboard.leaderboard.totalParticipants);
```
### Quest Rewards Preview
```javascript theme={null}
// Show potential rewards before quest participation
async function showQuestRewards(questId, userAddress, accessToken) {
const tracking = await trackQuestCompletion(questId, userAddress, accessToken);
if (tracking.error || tracking.message) {
console.log(tracking.error || tracking.message);
return;
}
console.log(`Quest: ${tracking.quest.name}`);
console.log(`Potential Points: +${tracking.quest.points}`);
console.log(`Current Points: ${tracking.user.currentPoints}`);
console.log(`After Completion: ${tracking.user.projectedPoints}`);
console.log(`Current Rank: ${tracking.user.currentRank || 'Unranked'}`);
}
```
### Achievement System
```javascript theme={null}
// Check user achievements
const userPoints = await findUserPoints(spaceId, userAddress, accessToken);
const achievements = calculateAchievements(userPoints.points);
console.log(`Current Level: ${achievements.current.name}`);
if (achievements.next) {
console.log(`Next Level: ${achievements.next.name} (${achievements.next.points} points)`);
console.log(`Progress: ${Math.round(achievements.progress * 100)}%`);
}
console.log(`Total Achievements: ${achievements.totalAchieved}/5`);
```
## Best Practices
1. **Search Optimization**: Limit user search to 20-50 pages max for UI responsiveness
2. **Caching**: Cache user positions for 5-10 minutes to reduce API calls
3. **Error Handling**: Handle cases where users are not found in rankings
4. **Performance**: Consider showing approximate positions rather than exact searches
5. **User Experience**: Clearly indicate when users are not yet ranked
## Limitations & Workarounds
### Current Limitations
1. **No Direct User Lookup**: Must search through leaderboard pages
2. **Search Performance**: Finding users can require multiple API calls
3. **No Sprint Management**: Sprint IDs come from external sources
### Recommended Workarounds
1. **Efficient Search**: Implement reasonable search limits
2. **Caching Strategy**: Cache user positions for short periods
3. **User Communication**: Set expectations about search time
4. **Achievement Systems**: Define point thresholds instead of exact rankings
## Points Integration Patterns
* **New User Onboarding**: Show potential points from available quests
* **Progress Tracking**: Regular user position checks (respect rate limits)
* **Achievement Systems**: Define point thresholds (100, 500, 1000, etc.)
* **Access Control**: Points-based feature unlocking
* **Quest Recommendations**: Suggest high-value quests based on current points
## Next Steps
* **[Quest Integration Guide](/galxe-integration/guides/quests)** - Quest-based point earning
* **[Leaderboard Guide](/galxe-integration/guides/leaderboards)** - Advanced ranking features
* **[Space API Reference](/galxe-integration/api-reference/space)** - Complete API documentation
# Quest Integration
Source: https://docs.galxe.com/galxe-integration/guides/quests
Build complete quest workflows with eligibility verification and status tracking
## Overview
Implement quest systems that handle:
* Quest validation and status checking
* User eligibility verification through credential groups
* Quest discovery and filtering
* Loyalty points tracking
## Basic Quest Operations
### Get Quest Details
```graphql theme={null}
query GetQuest($id: ID!) {
quest(id: $id) {
id
name
type
status
description
startTime
endTime
cap
participantsCount
loyaltyPoints
space {
id
name
}
chain
}
}
```
**Response**:
```json theme={null}
{
"data": {
"quest": {
"id": "GChdWUjXX3",
"name": "Introduction to Web3!",
"type": "Drop",
"status": "Active",
"description": "Welcome to Module 1-Course 1 of Mission Web3!",
"startTime": 1699200000,
"endTime": 1699800000,
"cap": 10000,
"participantsCount": 234163,
"loyaltyPoints": 100,
"space": {
"id": "40",
"name": "BNB Chain"
},
"chain": "BSC"
}
}
}
```
### List Space Quests
```graphql theme={null}
query GetSpaceQuests($spaceId: ID!, $first: Int!, $statuses: [QuestStatus!]) {
quests(input: {
spaceId: $spaceId
first: $first
statuses: $statuses
}) {
totalCount
pageInfo {
hasNextPage
endCursor
}
list {
id
name
type
status
participantsCount
loyaltyPoints
startTime
endTime
}
}
}
```
## Quest Status Reference
| Status | Description | When Used |
| ------------ | ---------------------------------------- | ------------------- |
| `Draft` | Quest in development | Before publishing |
| `Active` | Quest is live and accepting participants | During quest period |
| `NotStarted` | Quest published but not started | Before start time |
| `Expired` | Quest has ended | After end time |
| `CapReached` | Participant limit reached | When cap is full |
| `Deleted` | Quest removed | Removed quests |
## Quest Types
| Type | Description |
| -------------- | -------------------------- |
| `Drop` | NFT drop quest |
| `MysteryBox` | Mystery box reward |
| `Airdrop` | Token airdrop |
| `Points` | Loyalty points reward |
| `ExternalLink` | External link verification |
| `Bounty` | Bounty quest |
## User Eligibility Verification
### Check User Eligibility
```graphql theme={null}
query CheckUserEligibility($questId: ID!, $address: String!) {
quest(id: $questId) {
id
name
status
credentialGroups(address: $address) {
id
name
conditionRelation
conditions {
expression
eligible
}
rewards {
expression
eligible
rewardType
rewardCount
}
}
}
}
```
**Key Points**:
* When `conditions.eligible` is `true`, user meets requirements
* When `rewards.eligible` is `true`, user can claim rewards
* `conditionRelation` can be `ALL` (must meet all) or `ANY` (meet at least one)
## Basic Implementation
### Quest Validation
```javascript theme={null}
async function validateQuest(questId, accessToken) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetQuest($id: ID!) {
quest(id: $id) {
id
name
status
startTime
endTime
participantsCount
cap
}
}`,
variables: { id: questId }
})
});
const data = await response.json();
const quest = data.data.quest;
if (!quest) throw new Error('Quest not found');
// Check quest status
if (quest.status === 'Draft') throw new Error('Quest is in draft mode');
if (quest.status === 'Deleted') throw new Error('Quest has been deleted');
if (quest.status === 'Expired') throw new Error('Quest has expired');
if (quest.status === 'CapReached') throw new Error('Quest capacity reached');
// Check timing for active quests
if (quest.status === 'Active' && quest.startTime && quest.endTime) {
const now = Math.floor(Date.now() / 1000);
if (now < quest.startTime) throw new Error('Quest has not started yet');
if (now > quest.endTime) throw new Error('Quest has ended');
}
return quest;
}
```
### Check User Eligibility
```javascript theme={null}
async function checkUserEligibility(questId, userAddress, accessToken) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query CheckUserEligibility($questId: ID!, $address: String!) {
quest(id: $questId) {
id
name
status
credentialGroups(address: $address) {
id
name
conditionRelation
conditions {
expression
eligible
}
rewards {
expression
eligible
rewardType
rewardCount
}
}
}
}`,
variables: { questId, address: userAddress }
})
});
const data = await response.json();
const quest = data.data.quest;
if (!quest) throw new Error('Quest not found');
const eligibilityResults = quest.credentialGroups.map(group => {
// Check conditions based on relation (ALL or ANY)
const conditionsMet = group.conditionRelation === 'ALL'
? group.conditions.every(c => c.eligible)
: group.conditions.some(c => c.eligible);
const eligibleRewards = group.rewards.filter(r => r.eligible);
return {
groupId: group.id,
groupName: group.name,
conditionsMet,
eligibleRewards
};
});
const isEligible = eligibilityResults.some(r => r.conditionsMet && r.eligibleRewards.length > 0);
return {
questId,
userAddress,
isEligible,
eligibilityDetails: eligibilityResults,
questName: quest.name,
questStatus: quest.status
};
}
```
### Get Space Quests
```javascript theme={null}
async function getSpaceQuests(spaceId, accessToken, options = {}) {
const {
limit = 20,
cursor = null,
statuses = ['Active']
} = options;
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetSpaceQuests($input: ListQuestInput!) {
quests(input: $input) {
totalCount
pageInfo {
hasNextPage
endCursor
}
list {
id
name
type
status
participantsCount
loyaltyPoints
startTime
endTime
cap
}
}
}`,
variables: {
input: {
spaceId,
first: limit,
after: cursor,
statuses
}
}
})
});
const data = await response.json();
return data.data.quests;
}
```
## Quest Status Helpers
### Check Quest Phase
```javascript theme={null}
function getQuestPhase(quest) {
switch (quest.status) {
case 'NotStarted':
return 'not_started';
case 'Active':
if (quest.startTime && quest.endTime) {
const now = Math.floor(Date.now() / 1000);
if (now < quest.startTime) return 'scheduled';
if (now > quest.endTime) return 'ended_pending';
}
return 'active';
case 'Expired':
return 'expired';
case 'CapReached':
return 'full';
case 'Draft':
return 'draft';
case 'Deleted':
return 'deleted';
default:
return 'unknown';
}
}
function isQuestParticipable(quest) {
if (quest.status !== 'Active') return false;
// Check capacity
if (quest.cap > 0 && quest.participantsCount >= quest.cap) return false;
// Check timing
if (quest.startTime && quest.endTime) {
const now = Math.floor(Date.now() / 1000);
if (now < quest.startTime || now > quest.endTime) return false;
}
return true;
}
```
## Usage Examples
### Basic Quest Validation
```javascript theme={null}
// Validate quest before showing UI
const accessToken = process.env.GALXE_ACCESS_TOKEN;
try {
const quest = await validateQuest('GChdWUjXX3', accessToken);
console.log(`Quest "${quest.name}" is ${quest.status}`);
console.log(`Participants: ${quest.participantsCount}`);
const phase = getQuestPhase(quest);
const canParticipate = isQuestParticipable(quest);
console.log(`Phase: ${phase}`);
console.log(`Can participate: ${canParticipate}`);
} catch (error) {
console.error('Quest validation failed:', error.message);
}
```
### User Eligibility Check
```javascript theme={null}
// Check if user can participate
const userAddress = '0x1234567890123456789012345678901234567890';
const eligibility = await checkUserEligibility('GChdWUjXX3', userAddress, accessToken);
if (eligibility.isEligible) {
console.log('User is eligible for quest');
console.log('Available rewards:', eligibility.eligibilityDetails
.flatMap(group => group.eligibleRewards)
.map(reward => reward.expression)
);
} else {
console.log('User is not eligible for this quest');
console.log('Missing requirements:', eligibility.eligibilityDetails
.filter(group => !group.conditionsMet)
.map(group => group.groupName)
);
}
```
### Quest Discovery
```javascript theme={null}
// Get active quests for a space
const spaceQuests = await getSpaceQuests('40', accessToken, {
statuses: ['Active'],
limit: 10
});
console.log(`Found ${spaceQuests.totalCount} active quests`);
console.log('Quest list:');
spaceQuests.list.forEach(quest => {
console.log(`- ${quest.name} (${quest.loyaltyPoints} points, ${quest.participantsCount} participants)`);
});
```
### Complete Quest Check
```javascript theme={null}
async function createQuestDashboard(spaceId, userAddress, accessToken) {
// Get active quests
const quests = await getSpaceQuests(spaceId, accessToken, {
statuses: ['Active'],
limit: 10
});
// Check eligibility for top quests
const eligibilityChecks = await Promise.all(
quests.list.slice(0, 5).map(quest =>
checkUserEligibility(quest.id, userAddress, accessToken)
.then(result => ({ ...quest, eligibility: result }))
.catch(error => ({ ...quest, eligibility: { error: error.message } }))
)
);
const eligibleQuests = eligibilityChecks.filter(q => q.eligibility.isEligible);
const totalPoints = eligibleQuests.reduce((sum, q) => sum + q.loyaltyPoints, 0);
return {
space: { id: spaceId },
totalQuests: quests.totalCount,
checkedQuests: eligibilityChecks.length,
eligibleQuests: eligibleQuests.length,
potentialPoints: totalPoints,
quests: eligibilityChecks
};
}
```
## Best Practices
1. **Status Validation**: Always check quest status before showing participation UI
2. **Error Handling**: Handle cases where quests are not found or access is denied
3. **Rate Limiting**: Add delays when processing multiple quests or users
4. **Caching**: Cache quest details for 1-5 minutes to reduce API calls
5. **Capacity Monitoring**: Check both status and participant count vs cap
## Quest Lifecycle
| Status | User Actions | Next Status |
| ------------ | ------------------------------ | ------------------------- |
| `Draft` | None (not visible) | `NotStarted` or `Active` |
| `NotStarted` | View details, set reminders | `Active` |
| `Active` | Participate, check eligibility | `Expired` or `CapReached` |
| `CapReached` | View results only | `Expired` |
| `Expired` | View results only | N/A |
| `Deleted` | None (hidden) | N/A |
## Common Integration Patterns
* **Quest Discovery**: Filter by space, status, and type
* **Eligibility Pre-check**: Verify user can participate before showing UI
* **Status Monitoring**: Track quest lifecycle changes
* **Reward Tracking**: Monitor available rewards and claim status
* **Points Calculation**: Track potential loyalty points earnings
## Next Steps
* **[Quest API Reference](/galxe-integration/api-reference/quest)** - Complete API documentation
* **[Credential Integration](/galxe-integration/guides/user-verification)** - User verification workflows
* **[Loyalty Program](/galxe-integration/guides/loyalty-program)** - Points and rewards integration
# Starboard Integration Guide
Source: https://docs.galxe.com/galxe-integration/guides/starboards
Track Twitter influence and social metrics with rankings and engagement analytics
## Overview
Starboards provide Twitter influence tracking systems featuring:
* Real-time Twitter follower rankings
* Influence score calculations
* Social metrics with trend analysis
* Competitive leaderboards with detailed metrics
## Understanding Starboards
### Basic Starboard Information
```graphql theme={null}
query GetStarboard($id: ID!) {
starboard(id: $id) {
basicInfo {
id
name
projectName
description
tags
type
reward {
name
description
startTime
endTime
}
}
}
}
```
**Response**:
```json theme={null}
{
"data": {
"starboard": {
"basicInfo": {
"id": 1,
"name": "Twitter Influence Tracker",
"projectName": "Galxe Community",
"description": "Track your Twitter influence and compete with others",
"tags": ["social", "twitter", "influence"],
"type": "TWITTER",
"reward": {
"name": "Influence Rewards",
"description": "Rewards for top Twitter influencers",
"startTime": 1699200000,
"endTime": 1700000000
}
}
}
}
}
```
### Starboard Types
* **`TWITTER`**: Twitter-based influence tracking
* **`ONCHAIN`**: Blockchain activity-based rankings
## Leaderboard Queries
### Get Starboard Rankings
```graphql theme={null}
query GetStarboardRankings($starboardId: ID!, $first: Int!, $after: String) {
starboard(id: $starboardId) {
basicInfo {
id
name
type
}
leaderboard(
pagination: {
forward: {
first: $first
after: $after
}
}
) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
xUserProfile {
id
name
username
profileImageUrl
followersCount
verifiedType
}
rank {
value
delta
percentage
}
influenceScore {
value
delta
deltaRate
}
change24H {
value
delta
}
change7D {
value
delta
}
change30D {
value
delta
}
}
}
}
}
}
```
### Search Specific User
```graphql theme={null}
query SearchUserInStarboard($starboardId: ID!, $twitterId: String!) {
starboard(id: $starboardId) {
leaderboard(
twitterId: $twitterId
pagination: {
forward: { first: 1 }
}
) {
edges {
node {
xUserProfile {
username
followersCount
verifiedType
}
rank {
value
delta
percentage
}
influenceScore {
value
delta
deltaRate
}
}
}
}
}
}
```
## Basic Implementation
### Get Starboard Information
```javascript theme={null}
async function getStarboardInfo(starboardId, accessToken) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetStarboard($id: ID!) {
starboard(id: $id) {
basicInfo {
id
name
projectName
description
tags
type
reward {
name
description
startTime
endTime
}
}
}
}`,
variables: { id: starboardId }
})
});
const data = await response.json();
return data.data.starboard.basicInfo;
}
```
### Get Leaderboard Rankings
```javascript theme={null}
async function getLeaderboard(starboardId, accessToken, options = {}) {
const {
limit = 20,
cursor = null
} = options;
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetStarboardRankings($starboardId: ID!, $first: Int!, $after: String) {
starboard(id: $starboardId) {
basicInfo { id name type }
leaderboard(
pagination: {
forward: {
first: $first
after: $after
}
}
) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
xUserProfile {
id
name
username
profileImageUrl
followersCount
verifiedType
}
rank {
value
delta
percentage
}
influenceScore {
value
delta
deltaRate
}
change24H { value delta }
change7D { value delta }
change30D { value delta }
}
}
}
}
}`,
variables: {
starboardId,
first: limit,
after: cursor
}
})
});
const data = await response.json();
const starboard = data.data.starboard;
return {
starboardId,
name: starboard.basicInfo.name,
type: starboard.basicInfo.type,
rankings: starboard.leaderboard.edges.map(edge => ({
rank: parseInt(edge.node.rank.value),
rankDelta: edge.node.rank.delta,
rankPercentage: edge.node.rank.percentage,
score: parseFloat(edge.node.influenceScore.value),
scoreDelta: edge.node.influenceScore.delta,
scoreDeltaRate: edge.node.influenceScore.deltaRate,
user: {
id: edge.node.xUserProfile.id,
name: edge.node.xUserProfile.name,
username: edge.node.xUserProfile.username,
avatar: edge.node.xUserProfile.profileImageUrl,
followers: edge.node.xUserProfile.followersCount,
verified: edge.node.xUserProfile.verifiedType
},
trends: {
change24H: {
value: edge.node.change24H.value,
delta: edge.node.change24H.delta
},
change7D: {
value: edge.node.change7D.value,
delta: edge.node.change7D.delta
},
change30D: {
value: edge.node.change30D.value,
delta: edge.node.change30D.delta
}
}
})),
pageInfo: starboard.leaderboard.pageInfo
};
}
```
### Find User in Starboard
````javascript theme={null}
async function findUser(starboardId, twitterId, accessToken) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query SearchUserInStarboard($starboardId: ID!, $twitterId: String!) {
starboard(id: $starboardId) {
leaderboard(
twitterId: $twitterId
pagination: { forward: { first: 1 } }
) {
edges {
node {
xUserProfile {
username
followersCount
verifiedType
}
rank {
value
delta
percentage
}
influenceScore {
value
delta
deltaRate
}
}
}
}
}
}`,
variables: { starboardId, twitterId }
})
});
const data = await response.json();
const edges = data.data.starboard.leaderboard.edges;
if (edges.length === 0) {
return null;
}
const node = edges[0].node;
return {
username: node.xUserProfile.username,
followers: node.xUserProfile.followersCount,
verified: node.xUserProfile.verifiedType,
rank: parseInt(node.rank.value),
rankDelta: node.rank.delta,
rankPercentage: node.rank.percentage,
score: parseFloat(node.influenceScore.value),
scoreDelta: node.influenceScore.delta,
scoreDeltaRate: node.influenceScore.deltaRate
};
}
### Get Twitter Handle by EVM Address
```javascript
async function getTwitterHandleByEvmAddress(starboardId, evmAddress, accessToken) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetTwitterHandleByEvmAddress($starboardId: ID!, $evmAddress: String!) {
starboard(id: $starboardId) {
twitterHandleByEvmAddress(evmAddress: $evmAddress) {
evmAddress
mainAddress
twitterHandle
isPublic
}
}
}`,
variables: { starboardId, evmAddress }
})
});
const data = await response.json();
const result = data.data.starboard.twitterHandleByEvmAddress;
if (!result) {
return null;
}
return {
evmAddress: result.evmAddress,
mainAddress: result.mainAddress,
twitterHandle: result.twitterHandle,
isPublic: result.isPublic
};
}
### Get User Detail by EVM Address
```javascript
async function getUserDetailByEvmAddress(starboardId, evmAddress, accessToken) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetUserDetail($starboardId: ID!, $evmAddress: String!) {
starboard(id: $starboardId) {
userDetail(evmAddress: $evmAddress) {
starboardId
twitterHandle
individual
aura
isPublic
}
}
}`,
variables: { starboardId, evmAddress }
})
});
const data = await response.json();
const result = data.data.starboard.userDetail;
if (!result) {
return null;
}
return {
starboardId: result.starboardId,
twitterHandle: result.twitterHandle,
individual: result.individual,
aura: result.aura,
isPublic: result.isPublic
};
}
````
## Analytics Functions
### User Trend Analysis
```javascript theme={null}
async function analyzeUserTrends(starboardId, twitterId, accessToken) {
const user = await findUser(starboardId, twitterId, accessToken);
if (!user) {
return { message: 'User not found in starboard' };
}
return {
user: {
username: user.username,
followers: user.followers,
verified: user.verified
},
ranking: {
current: user.rank,
delta: user.rankDelta,
percentile: user.rankPercentage
},
influence: {
score: user.score,
delta: user.scoreDelta,
growthRate: user.scoreDeltaRate
},
performance: {
trending: user.scoreDelta > 0 ? 'up' : user.scoreDelta < 0 ? 'down' : 'stable',
momentum: Math.abs(user.scoreDeltaRate) > 0.1 ? 'high' : 'low'
}
};
}
```
### Top Performers Analysis
```javascript theme={null}
async function getTopPerformers(starboardId, accessToken, limit = 10) {
const leaderboard = await getLeaderboard(starboardId, accessToken, { limit });
return {
topInfluencers: leaderboard.rankings
.sort((a, b) => b.score - a.score)
.slice(0, 5),
fastestGrowing: leaderboard.rankings
.filter(user => user.scoreDeltaRate > 0)
.sort((a, b) => b.scoreDeltaRate - a.scoreDeltaRate)
.slice(0, 5),
biggestMovers: leaderboard.rankings
.filter(user => Math.abs(user.rankDelta) > 0)
.sort((a, b) => Math.abs(b.rankDelta) - Math.abs(a.rankDelta))
.slice(0, 5)
};
}
```
## Usage Examples
### Basic Starboard Setup
```javascript theme={null}
const accessToken = process.env.GALXE_ACCESS_TOKEN;
// Get starboard information
const starboard = await getStarboardInfo('1', accessToken);
console.log(`Starboard: ${starboard.name} (${starboard.type})`);
// Get top 10 rankings
const leaderboard = await getLeaderboard('1', accessToken, { limit: 10 });
console.log('Top 10 Twitter influencers:');
leaderboard.rankings.forEach(user => {
console.log(`${user.rank}. @${user.user.username} - ${user.score} points (${user.user.followers} followers)`);
});
```
### User Lookup and Analysis
```javascript theme={null}
// Find specific user by Twitter ID
const userAnalysis = await analyzeUserTrends('1', 'elonmusk', accessToken);
if (userAnalysis.message) {
console.log(userAnalysis.message);
} else {
console.log(`@${userAnalysis.user.username}`);
console.log(`Rank: #${userAnalysis.ranking.current} (${userAnalysis.ranking.delta > 0 ? '+' : ''}${userAnalysis.ranking.delta})`);
console.log(`Score: ${userAnalysis.influence.score} (${userAnalysis.performance.trending})`);
}
// Get Twitter handle by EVM address
const twitterInfo = await getTwitterHandleByEvmAddress('1', '0x1234567890abcdef', accessToken);
if (twitterInfo) {
console.log(`Address ${twitterInfo.evmAddress} is linked to @${twitterInfo.twitterHandle}`);
console.log(`Main address: ${twitterInfo.mainAddress}`);
console.log(`Public profile: ${twitterInfo.isPublic}`);
}
// Get detailed user metrics by EVM address
const userDetail = await getUserDetailByEvmAddress('1', '0x1234567890abcdef', accessToken);
if (userDetail) {
console.log(`@${userDetail.twitterHandle} metrics:`);
console.log(`Individual score: ${userDetail.individual}`);
console.log(`Aura score: ${userDetail.aura}`);
console.log(`Public profile: ${userDetail.isPublic}`);
}
```
### Top Performers Dashboard
```javascript theme={null}
// Get top performers analysis
const performers = await getTopPerformers('1', accessToken);
console.log('Top Influencers:');
performers.topInfluencers.forEach(user => {
console.log(`@${user.user.username}: ${user.score} points`);
});
console.log('\nFastest Growing:');
performers.fastestGrowing.forEach(user => {
console.log(`@${user.user.username}: +${user.scoreDeltaRate}% growth`);
});
console.log('\nBiggest Rank Changes:');
performers.biggestMovers.forEach(user => {
console.log(`@${user.user.username}: ${user.rankDelta > 0 ? '+' : ''}${user.rankDelta} positions`);
});
```
## Understanding Metrics
### Rank Metrics
* **`value`**: Current ranking position
* **`delta`**: Change in position since last update
* **`percentage`**: Percentile ranking (higher = better)
### Influence Score
* **`value`**: Current influence score
* **`delta`**: Absolute change in score
* **`deltaRate`**: Percentage growth rate
### Trend Data
* **`change24H`**: 24-hour performance metrics
* **`change7D`**: 7-day performance metrics
* **`change30D`**: 30-day performance metrics
## Best Practices
1. **Caching**: Cache leaderboard data for 1-2 minutes to reduce API calls
2. **Rate Limiting**: Limit updates to reasonable frequencies
3. **Error Handling**: Handle cases where users are not found in rankings
4. **Trend Analysis**: Focus on delta values and percentages for meaningful insights
5. **User Context**: Always display Twitter usernames for clarity
## Common Integration Patterns
* **Influencer Discovery**: Find top performers and trending users
* **Competition Tracking**: Monitor rank changes and performance
* **User Verification**: Check Twitter verification status
* **Trend Analysis**: Identify growth patterns and momentum
* **Performance Comparison**: Compare multiple users or time periods
* **Address-to-Twitter Mapping**: Link EVM addresses to Twitter profiles using `twitterHandleByEvmAddress`
* **User Metrics by Address**: Get detailed user scores (individual, aura) using `userDetail`
* **Cross-Platform Identity**: Connect on-chain addresses with social media presence
## Next Steps
* **[Starboard API Reference](/galxe-integration/api-reference/starboard)** - Complete API documentation
* **[Leaderboard Guide](/galxe-integration/guides/leaderboards)** - General ranking patterns
* **[Authentication](/galxe-integration/getting-started/authentication)** - Access token setup
# User Verification & Credential Validation
Source: https://docs.galxe.com/galxe-integration/guides/user-verification
Implement user eligibility verification using Galxe's credential system for access control
## Overview
Galxe's B2B Credential API provides **read-only** access for:
* User eligibility verification
* Credential information retrieval
* Access control validation
* Requirement checking
**Important**: The B2B API is designed for verification and querying only. Credential management is handled through the [Galxe Dashboard](https://galxe.com).
## Understanding Credentials
Credentials are verification proofs that users earn through various activities:
### Popular Credential Types
* **`EVM_ADDRESS`**: Ethereum-compatible wallet verification
* **`SOLANA_ADDRESS`**: Solana wallet verification
* **`TWITTER`**: Twitter-based verification
* **`DISCORD`**: Discord membership verification
* **`GITHUB`**: GitHub contribution verification
* **`EMAIL`**: Email verification
### Common Verification Methods
* **Social Media**: `TWITTER_FOLLOW`, `DISCORD_MEMBER`, `GITHUB_CONTRIBUTOR`
* **Blockchain**: `CONTRACT_NFT_HOLDER`, `WALLET_BALANCE`, `SNAPSHOT_ORG`
* **Interactive**: `QUIZ`, `SURVEY`, `VISIT_LINK`
* **Custom**: `API`, `REST`, `GRAPHQL`
## Basic Credential Queries
### Get Credential Information
```graphql theme={null}
query GetCredentialInfo($credId: ID!) {
credential(id: $credId) {
id
name
description
credType
credSource
referenceLink
itemCount
lastUpdate
syncStatus
curatorSpace {
id
name
}
chain
}
}
```
**Response**:
```json theme={null}
{
"data": {
"credential": {
"id": "312969464",
"name": "Twitter Follower Verification",
"description": "Users who follow @galxe on Twitter",
"credType": "TWITTER",
"credSource": "TWITTER_FOLLOW",
"referenceLink": "https://twitter.com/galxe",
"itemCount": 150000,
"lastUpdate": 1699200000,
"syncStatus": "SYNCED",
"curatorSpace": {
"id": "40",
"name": "BNB Chain"
},
"chain": "BSC"
}
}
}
```
### Check User Eligibility
```graphql theme={null}
query CheckUserEligibility($credId: ID!, $address: String!) {
credential(id: $credId) {
id
name
eligible(address: $address)
credType
credSource
syncStatus
}
}
```
**Response**:
```json theme={null}
{
"data": {
"credential": {
"id": "312969464",
"name": "Twitter Follower Verification",
"eligible": 1,
"credType": "TWITTER",
"credSource": "TWITTER_FOLLOW",
"syncStatus": "SYNCED"
}
}
}
```
**Eligibility Values**:
* `1`: User is eligible
* `0`: User is not eligible
### Quest-Specific Eligibility
```graphql theme={null}
query CheckQuestEligibility($credId: ID!, $address: String!, $campaignId: ID!) {
credential(id: $credId) {
eligible(address: $address, campaignId: $campaignId)
name
syncStatus
}
}
```
## Basic Implementation
### Get Credential Information
```javascript theme={null}
async function getCredentialInfo(credId, accessToken) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query GetCredentialInfo($credId: ID!) {
credential(id: $credId) {
id
name
description
credType
credSource
referenceLink
itemCount
lastUpdate
syncStatus
curatorSpace {
id
name
}
chain
}
}`,
variables: { credId }
})
});
const data = await response.json();
return data.data.credential;
}
```
### Verify User Eligibility
```javascript theme={null}
async function verifyUserEligibility(credId, userAddress, accessToken, campaignId = null) {
const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'access-token': accessToken
},
body: JSON.stringify({
query: `query CheckUserEligibility($credId: ID!, $address: String!, $campaignId: ID) {
credential(id: $credId) {
id
name
eligible(address: $address, campaignId: $campaignId)
credType
credSource
syncStatus
lastSync
}
}`,
variables: { credId, address: userAddress, campaignId }
})
});
const data = await response.json();
const credential = data.data.credential;
return {
credentialId: credential.id,
credentialName: credential.name,
isEligible: credential.eligible === 1,
credentialType: credential.credType,
credentialSource: credential.credSource,
isActive: credential.syncStatus === 'SYNCED',
lastSync: credential.lastSync,
userAddress,
campaignId
};
}
```
### Verify Multiple Credentials
```javascript theme={null}
async function verifyMultipleCredentials(credentialIds, userAddress, accessToken, campaignId = null) {
const verificationPromises = credentialIds.map(credId =>
verifyUserEligibility(credId, userAddress, accessToken, campaignId)
.catch(error => ({
credentialId: credId,
error: error.message,
isEligible: false,
userAddress,
campaignId
}))
);
const results = await Promise.all(verificationPromises);
const passed = results.filter(result => result.isEligible && !result.error);
const failed = results.filter(result => !result.isEligible || result.error);
return {
userAddress,
campaignId,
totalChecked: credentialIds.length,
passed: passed.length,
failed: failed.length,
allPassed: passed.length === credentialIds.length,
results: { passed, failed }
};
}
```
## Access Control System
### Simple Access Control
```javascript theme={null}
async function checkAccess(userAddress, requiredCredentials, accessToken, campaignId = null) {
const verification = await verifyMultipleCredentials(
requiredCredentials.map(req => req.credentialId),
userAddress,
accessToken,
campaignId
);
// Check if all required credentials are met
const requiredIds = requiredCredentials
.filter(req => req.required !== false)
.map(req => req.credentialId);
const passedRequired = verification.results.passed.filter(result =>
requiredIds.includes(result.credentialId)
);
const hasAccess = passedRequired.length === requiredIds.length;
return {
hasAccess,
userAddress,
campaignId,
requirements: {
total: requiredCredentials.length,
required: requiredIds.length,
satisfied: passedRequired.length
},
details: verification,
missing: requiredCredentials.filter(req =>
req.required !== false &&
!passedRequired.some(passed => passed.credentialId === req.credentialId)
)
};
}
```
## Usage Examples
### Basic Verification
```javascript theme={null}
const accessToken = process.env.GALXE_ACCESS_TOKEN;
// Check single user eligibility
const result = await verifyUserEligibility(
'312969464', // Twitter follower credential
'0x1234567890123456789012345678901234567890',
accessToken
);
console.log(`User eligible: ${result.isEligible}`);
console.log(`Credential: ${result.credentialName}`);
console.log(`Type: ${result.credentialType}`);
```
### Multi-Credential Verification
```javascript theme={null}
// Check multiple requirements
const credentialIds = ['312969464', '312969465', '312969466'];
const userAddress = '0x1234567890123456789012345678901234567890';
const multiResult = await verifyMultipleCredentials(credentialIds, userAddress, accessToken);
console.log(`Passed: ${multiResult.passed}/${multiResult.totalChecked} credentials`);
console.log(`Access granted: ${multiResult.allPassed}`);
if (!multiResult.allPassed) {
console.log('Failed credentials:', multiResult.results.failed.map(f => f.credentialName || f.credentialId));
}
```
### Quest-Specific Verification
```javascript theme={null}
// Check eligibility for specific quest
const questResult = await verifyUserEligibility(
'312969464',
userAddress,
accessToken,
'GChdWUjXX3' // Quest ID
);
console.log(`Quest eligible: ${questResult.isEligible}`);
```
### Access Control System
```javascript theme={null}
// Define access requirements
const requirements = [
{ credentialId: '312969464', description: 'Twitter Follower', required: true },
{ credentialId: '312969465', description: 'Discord Member', required: true },
{ credentialId: '312969466', description: 'NFT Holder', required: false }
];
// Check user access
const accessCheck = await checkAccess(userAddress, requirements, accessToken);
if (accessCheck.hasAccess) {
console.log('Access granted!');
console.log(`Satisfied ${accessCheck.requirements.satisfied}/${accessCheck.requirements.required} required credentials`);
} else {
console.log('Access denied. Missing requirements:');
accessCheck.missing.forEach(req => {
console.log(`- ${req.description}`);
});
}
```
## Common Patterns
### User Onboarding Flow
```javascript theme={null}
async function onboardUser(userAddress, accessToken) {
const requiredCredentials = [
{ credentialId: '312969464', description: 'Twitter Follower', required: true },
{ credentialId: '312969465', description: 'Discord Member', required: true }
];
const verification = await verifyMultipleCredentials(
requiredCredentials.map(r => r.credentialId),
userAddress,
accessToken
);
if (verification.allPassed) {
return {
status: 'approved',
message: 'Welcome! All requirements met.'
};
} else {
const missing = requiredCredentials.filter(req =>
!verification.results.passed.some(p => p.credentialId === req.credentialId)
);
return {
status: 'pending',
message: `Please complete: ${missing.map(m => m.description).join(', ')}`,
missingCredentials: missing
};
}
}
```
### Access Gate Implementation
```javascript theme={null}
async function checkGateAccess(userAddress, requiredCredId, accessToken, questId = null) {
const result = await verifyUserEligibility(requiredCredId, userAddress, accessToken, questId);
return {
allowed: result.isEligible,
reason: result.isEligible ? 'Access granted' : `Missing: ${result.credentialName}`,
credentialInfo: {
name: result.credentialName,
type: result.credentialType,
source: result.credentialSource
}
};
}
```
## Sync Status Handling
### Check Credential Sync Status
Credentials have different sync statuses that affect reliability:
* **`SYNCED`**: Data is current and reliable
* **`SYNCING`**: Data is being updated, may be stale
```javascript theme={null}
async function waitForSync(credId, accessToken, maxWaitMs = 60000) {
const startTime = Date.now();
while (Date.now() - startTime < maxWaitMs) {
const info = await getCredentialInfo(credId, accessToken);
if (info.syncStatus === 'SYNCED') {
return { synced: true, waited: Date.now() - startTime };
}
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
}
return { synced: false, waited: maxWaitMs };
}
// Usage
const syncCheck = await waitForSync('312969464', accessToken);
if (syncCheck.synced) {
console.log(`Credential synced after ${syncCheck.waited}ms`);
// Now safe to check eligibility
} else {
console.log('Credential still syncing, results may be stale');
}
```
## Best Practices
1. **Caching**: Cache eligibility results for 5-10 minutes to reduce API calls
2. **Sync Status**: Check `syncStatus` field before relying on eligibility results
3. **Error Handling**: Always handle network errors and invalid credential IDs
4. **Quest Context**: Use `campaignId` parameter for quest-specific verifications
5. **Rate Limiting**: Implement delays between batch requests (200-500ms)
## Understanding Sync Status
* Always check the `syncStatus` field in responses
* Only rely on results when status is `SYNCED`
* For critical verifications, consider waiting for sync completion
* Cache results appropriately based on sync status
## Next Steps
* **[Quest Integration](/galxe-integration/guides/quests)** - Using credentials in quest requirements
* **[Credential API Reference](/galxe-integration/api-reference/credential)** - Complete API documentation
* **[Authentication](/galxe-integration/getting-started/authentication)** - Access token setup
# Galxe Integration
Source: https://docs.galxe.com/galxe-integration/introduction
Build powerful Web3 experiences with Galxe's comprehensive GraphQL API
## Learning Resources
Get your first API call working in 3 minutes
Ready-to-use code snippets and GraphQL queries
Secure API access and token management
Handle errors and troubleshoot issues
Interactive GraphQL playground for testing queries
## API Reference
Manage quests and check user eligibility
Leaderboards, loyalty points, and rankings
User verification and credential management
Twitter influence tracking and social metrics
## Integration Guides
Complete quest workflow implementation
Real-time rankings and competitions
Points, rewards, and user engagement
Identity verification and access control
# Changelog
Source: https://docs.galxe.com/galxe-integration/resources/changelog
Track the latest updates, new features, and important changes to Galxe Integration API
## Initial Release - July 10, 2025
**Launch Date**: July 10, 2025
This marks the initial release of Galxe Integration API documentation.
### What's Included
* Complete API Reference
* Integration Guides
* Quick Start Guide
* Code Examples
* Error Handling Documentation
***
*This changelog will be updated with future releases and improvements.*
# Error Handling Guide
Source: https://docs.galxe.com/galxe-integration/resources/error-handling
Comprehensive guide to handling Galxe API errors, including error codes, response formats, and troubleshooting strategies
## Error Response Format
All API errors follow a consistent GraphQL error format:
```json theme={null}
{
"errors": [
{
"message": "Invalid access token: invalid token",
"extensions": {
"category": "AUTHENTICATION",
"code": "INVALID_TOKEN",
"details": [
"reason: invalid token"
],
"http_status": 401,
"request_id": "3e79b5c7c12964230e21ad6548c1bfe9",
"timestamp": "2025-07-10T14:26:35.41989024Z"
}
}
],
"data": null
}
```
## HTTP Status Codes
| Status Code | Description | Common Causes |
| ----------- | --------------------- | ----------------------------------------------- |
| `200` | Success | Request processed successfully |
| `400` | Bad Request | Invalid query syntax, missing required fields |
| `401` | Unauthorized | Missing or invalid access token |
| `403` | Forbidden | Insufficient permissions for requested resource |
| `429` | Too Many Requests | Rate limit exceeded |
| `500` | Internal Server Error | Server-side error, usually temporary |
| `502` | Bad Gateway | Service temporarily unavailable |
| `503` | Service Unavailable | Maintenance or high load |
## Error Categories
### Authentication Errors (`AUTHENTICATION`)
#### `INVALID_TOKEN` - Invalid Access Token
**Cause**: Missing, expired, or invalid access token.
```json theme={null}
{
"errors": [
{
"message": "Invalid access token: invalid token",
"extensions": {
"category": "AUTHENTICATION",
"code": "INVALID_TOKEN",
"details": ["reason: invalid token"],
"http_status": 401,
"request_id": "3e79b5c7c12964230e21ad6548c1bfe9",
"timestamp": "2025-07-10T14:26:35.41989024Z"
}
}
]
}
```
**Solution**: Check access token is correctly set in headers. Regenerate token from [Galxe Dashboard Settings](https://app.galxe.com/settings) if necessary.
#### `TOKEN_REQUIRED` - Missing Access Token
**Cause**: No access token provided in request headers.
**Solution**: Include `access-token` header in all API requests.
### Authorization Errors (`AUTHORIZATION`)
#### `PERMISSION_DENIED` - Insufficient Permissions
**Cause**: Token doesn't have permission to access the requested resource.
```json theme={null}
{
"errors": [
{
"message": "Permission denied",
"extensions": {
"category": "AUTHORIZATION",
"code": "PERMISSION_DENIED",
"http_status": 403
}
}
]
}
```
**Solution**: Ensure your access token has correct permissions for the space/credential you're accessing.
### Rate Limiting Errors (`RATE_LIMIT`)
#### `QUOTA_EXCEEDED` - API Quota Exceeded
**Cause**: Exceeded monthly API quota or rate limits.
```json theme={null}
{
"errors": [
{
"message": "API quota exceeded: monthly limit reached",
"extensions": {
"category": "RATE_LIMIT",
"code": "QUOTA_EXCEEDED",
"http_status": 429,
"details": ["monthly limit reached"]
}
}
]
}
```
**Solution**: Implement exponential backoff retry logic. Monitor usage and consider upgrading to higher rate limits if needed.
### Validation Errors (`VALIDATION`)
#### `INVALID_ARGUMENT` - Invalid Input Parameters
**Cause**: Invalid parameters, wrong data types, or missing required fields.
```json theme={null}
{
"errors": [
{
"message": "Invalid argument provided",
"extensions": {
"category": "VALIDATION",
"code": "INVALID_ARGUMENT",
"http_status": 400
}
}
]
}
```
**Solution**: Validate input parameters and ensure correct data types before sending requests.
#### `INVALID_ADDRESS` - Invalid Address Format
**Cause**: Malformed wallet address.
**Solution**: Validate address format (e.g., 42-character hex string for Ethereum addresses starting with `0x`).
#### `COMPLEXITY_LIMIT_EXCEEDED` - Query Too Complex
**Cause**: GraphQL query exceeds complexity limits.
```json theme={null}
{
"errors": [
{
"message": "Query complexity limit exceeded: 1500 > 1000",
"extensions": {
"category": "VALIDATION",
"code": "COMPLEXITY_LIMIT_EXCEEDED",
"http_status": 400,
"details": ["limit: 1000", "actual: 1500"]
}
}
]
}
```
**Solution**: Break complex queries into smaller parts or use pagination to reduce query complexity.
#### `DEPTH_LIMIT_EXCEEDED` - Query Too Deep
**Cause**: GraphQL query exceeds maximum depth limit.
**Solution**: Reduce query nesting depth and use flatter query structures.
### Not Found Errors (`NOT_FOUND`)
#### `NOT_FOUND` - Resource Not Found
**Cause**: Querying non-existent quests, credentials, or spaces.
```json theme={null}
{
"errors": [
{
"message": "Quest not found: invalid_id",
"extensions": {
"category": "NOT_FOUND",
"code": "NOT_FOUND",
"http_status": 404
}
}
]
}
```
**Solution**: Verify resource IDs are correct and the resource exists. Check permissions to access the resource.
#### Specific Resource Errors
* `SPACE_NOT_FOUND` - Space does not exist or is not accessible
* `QUEST_NOT_FOUND` - Quest does not exist or is not accessible
* `CREDENTIAL_NOT_FOUND` - Credential does not exist or is not accessible
* `USER_NOT_FOUND` - User does not exist or is not accessible
### Server Errors (`INTERNAL`)
#### `INTERNAL_ERROR` - Server Issues
**Cause**: Temporary server problems, database issues, or service outages.
```json theme={null}
{
"errors": [
{
"message": "Internal server error",
"extensions": {
"category": "INTERNAL",
"code": "INTERNAL_ERROR",
"http_status": 500
}
}
]
}
```
**Solution**: Retry after short delay. Contact support if error persists.
### Service Availability (`UNAVAILABLE`)
#### `UNAVAILABLE` - Service Unavailable
**Cause**: Service temporarily unavailable due to maintenance or high load.
**Solution**: Retry with exponential backoff. Check [API Status](https://status.galxe.com) for maintenance windows.
## Error Handling Best Practices
### 1. Check Error Categories
Always check the `extensions.category` field to understand the type of error:
* **`AUTHENTICATION`/`AUTHORIZATION`** - Fix token/permissions, don't retry
* **`VALIDATION`** - Fix request parameters, don't retry
* **`RATE_LIMIT`** - Implement backoff and retry
* **`NOT_FOUND`** - Verify resource exists, don't retry
* **`INTERNAL`/`UNAVAILABLE`** - Retry with backoff
### 2. Use Request IDs for Support
Include the `request_id` from error responses when contacting support for faster troubleshooting.
### 3. Implement Retry Logic
For `RATE_LIMIT`, `INTERNAL`, and `UNAVAILABLE` errors, implement exponential backoff:
```javascript theme={null}
// Basic retry example
async function retryRequest(operation, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
const shouldRetry = ['QUOTA_EXCEEDED', 'INTERNAL_ERROR', 'UNAVAILABLE']
.includes(error.extensions?.code);
if (shouldRetry && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
}
```
### 4. Monitor Error Patterns
Log and monitor error frequencies to identify:
* Repeated authentication failures (token issues)
* High rate limiting (need for optimization)
* Validation errors (client-side bugs)
* Service availability issues
## Troubleshooting Guide
### Quick Fixes
| Error Type | First Steps |
| ------------------ | -------------------------------------------------------- |
| **Authentication** | Verify access token is valid and properly set in headers |
| **Rate Limiting** | Reduce request frequency, implement backoff logic |
| **Validation** | Check parameter formats, data types, and required fields |
| **Not Found** | Verify resource IDs and check permissions |
| **Server Errors** | Retry after delay, check API status page |
### Debug Checklist
1. **Verify Request Format**
* Correct GraphQL syntax
* Valid JSON structure
* Required headers present
2. **Check Authentication**
* Access token valid and not expired
* Token has permissions for requested resources
* Headers properly formatted
3. **Validate Parameters**
* Correct data types (Int, String, Boolean)
* Required fields provided
* Address formats valid
4. **Monitor Limits**
* Stay within rate limits (10 QPS for free tier)
* Keep query complexity reasonable
* Use pagination for large datasets
## API Status and Support
* **Status Page**: [https://status.galxe.com](https://status.galxe.com)
* **Support Email**: [support@galxe.com](mailto:support@galxe.com)
* **Response Times**: 12-24 hours for technical issues
When reporting issues, include:
* Error message and request\_id
* Query that caused the error
* Expected vs actual behavior
* Environment details
## Next Steps
* **[Rate Limits](/galxe-integration/resources/rate-limits)** - Understanding API limits
* **[Support & Community](/galxe-integration/resources/support)** - Getting help
* **[Quick Start](/galxe-integration/getting-started/quick-start)** - Basic implementation
* **[Authentication](/galxe-integration/getting-started/authentication)** - Token setup
# Rate Limits & Usage Quotas
Source: https://docs.galxe.com/galxe-integration/resources/rate-limits
Understanding API rate limits, usage quotas, and best practices for the Galxe Integration API
To help manage the sheer volume of requests we receive on our API, we have implemented both rate limits and usage quotas. These limits help us provide the reliable and scalable API that our developer community relies on.
## Rate Limits & Quotas
Our API has two types of limits:
* **Rate Limits**: Maximum queries per second (QPS) you can send
* **Usage Quotas**: Total number of requests allowed per month
### Free Tier Limits
| Endpoint | Rate Limit | Monthly Quota |
| ------------------------------------------------------------------------------------------------ | ---------- | ---------------- |
| [https://graphigo-business.prd.galaxy.eco/query](https://graphigo-business.prd.galaxy.eco/query) | 10 QPS | 100,000 requests |
### What Happens When Limits Are Exceeded
#### Rate Limit Exceeded
When your application exceeds the rate limit (10 QPS), the API will return a `HTTP 429 Too Many Requests` response code. You should implement exponential backoff and retry logic to handle these responses.
#### Monthly Quota Exceeded
When you reach your monthly quota (100k requests), the API will return a `HTTP 429 Too Many Requests` response code until the next billing cycle begins.
## Enterprise Plans
Need higher limits? Contact our team for enterprise pricing that includes:
* **Higher Rate Limits**: Up to 1000+ QPS
* **Increased Quotas**: 10 Millions of requests per month
* **Priority Support**: Dedicated technical support
* **SLA Guarantees**: Uptime and response time guarantees
# Support & Community
Source: https://docs.galxe.com/galxe-integration/resources/support
Get the help you need and connect with the Galxe developer community
## 🚀 Getting Started
### First Time Here?
Get up and running in 5 minutes with our comprehensive quick start guide
Set up your access tokens and authentication
Learn the most common integration patterns
Complete API documentation and examples
## 💬 Community Channels
### Social Media
Follow for updates and announcements
Access code repositories and examples
Read technical articles and tutorials
## 🆘 Getting Help
### Self-Service Resources
Before reaching out for support, check these resources:
* **[Quick Start Guide](/galxe-integration/getting-started/quick-start)** - Basic setup and first API call
* **[API Reference](/galxe-integration/api-reference/quest)** - Complete API documentation
* **[Integration Guides](/galxe-integration/guides/quests)** - Scenario-based tutorials
* **[Error Handling](/galxe-integration/resources/error-handling)** - Troubleshooting common issues
* **[Error Codes](/galxe-integration/resources/error-handling)** - Complete error reference
* **[Rate Limits](/galxe-integration/resources/rate-limits)** - Understanding API limits
* **[Common Issues](#common-issues)** - Frequently encountered problems
* **[Debug Checklist](#debug-checklist)** - Step-by-step debugging guide
* **Code Examples** - Working code in multiple languages
* **Integration Patterns** - Common implementation approaches
* **Best Practices** - Recommended development practices
* **Sample Projects** - Complete example applications
### Direct Support
For complex issues or when you need direct assistance:
Before contacting support, please review our documentation and try the troubleshooting steps. This helps us provide faster, more targeted assistance.
#### Developer Support Email
**[support@galxe.com](mailto:support@galxe.com)**
**What to Include:**
* Clear description of the issue
* Steps to reproduce the problem
* Expected vs. actual behavior
* Code snippets (if applicable)
* Error messages and stack traces
* Your environment details
#### Response Times
* **General Inquiries**: 24-48 hours
* **Technical Issues**: 12-24 hours
* **Critical Issues**: 2-4 hours
## 🐛 Reporting Issues
### Bug Reports
Found a bug? Help us improve by reporting it properly.
**Where to Report:**
* **Critical Issues**: Email [support@galxe.com](mailto:support@galxe.com) immediately
* **General Bugs**: Create a GitHub issue
* **Documentation Issues**: Discord or GitHub
**Bug Report Template:**
```markdown theme={null}
## Bug Description
Brief description of the issue
## Steps to Reproduce
1. Step one
2. Step two
3. Step three
## Expected Behavior
What should happen
## Actual Behavior
What actually happens
## Environment
- Platform: [Web/Mobile/Server]
- Language: [JavaScript/Python/etc.]
- SDK Version: [if applicable]
- Browser: [if applicable]
## Additional Context
Any other relevant information
```
### Feature Requests
Have an idea for a new feature? We'd love to hear it!
**How to Submit:**
1. Check existing feature requests first
2. Create a detailed proposal
3. Explain the use case and benefits
4. Discuss with the community
## 🏆 Community Guidelines
### Code of Conduct
We're committed to providing a welcoming and inclusive environment:
* **Be Respectful**: Treat everyone with respect and kindness
* **Be Constructive**: Provide helpful feedback and suggestions
* **Be Patient**: Remember that everyone has different skill levels
* **Be Professional**: Keep discussions focused and on-topic
### Best Practices for Getting Help
Check documentation, existing issues, and community discussions
Provide clear, detailed descriptions of your issue
Share relevant code, error messages, and environment details
Respond to clarifying questions and update on resolution
## 🔍 Common Issues
### Authentication Problems
**Symptoms**: 401 Unauthorized errors
**Solutions**:
* Verify token is correctly set in headers
* Check token hasn't expired
* Ensure token has correct permissions
* Regenerate token if necessary
**Symptoms**: 403 Forbidden errors
**Solutions**:
* Verify token has access to the specific space/credential
* Check if you're an admin of the space
* Ensure the resource exists and is accessible
### API Request Issues
**Symptoms**: 429 Too Many Requests
**Solutions**:
* Implement exponential backoff
* Reduce request frequency
* Use batch operations where possible
* Cache responses to reduce redundant calls
**Symptoms**: Timeout or complexity errors
**Solutions**:
* Break large queries into smaller ones
* Use pagination for large datasets
* Reduce query depth and complexity
* Consider using multiple simpler queries
### Data Issues
**Symptoms**: Empty responses or null data
**Solutions**:
* Verify resource IDs are correct
* Check if resource exists and is accessible
* Ensure proper permissions
* Try with known working IDs
**Symptoms**: Validation errors
**Solutions**:
* Check data types and formats
* Validate addresses and IDs
* Review required vs optional fields
* Test with minimal valid data first
## 🛠️ Debug Checklist
When troubleshooting issues, follow this systematic approach:
### Pre-flight Checks
* [ ] Access token is set correctly
* [ ] Network connectivity is working
* [ ] Required dependencies are installed
* [ ] Environment variables are configured
* [ ] Token is valid and not expired
* [ ] Token has correct permissions
* [ ] Headers are properly formatted
* [ ] Using correct endpoint URL
* [ ] GraphQL query syntax is valid
* [ ] Required parameters are provided
* [ ] Data types match schema requirements
* [ ] Variable names match query definitions
### Testing Steps
Start with the simplest possible query to verify basic connectivity
Gradually add complexity to isolate the problematic component
Test with examples from documentation to verify your setup
Carefully review error messages and status codes for clues
### Maintenance Windows
We perform regular maintenance to ensure optimal performance:
* **Scheduled Maintenance**: Announced 24-48 hours in advance
* **Emergency Maintenance**: Minimal disruption, usually under 15 minutes
* **Status Notifications**: Subscribe for real-time updates
## Need Immediate Help?
Get real-time help from the community and team
Direct support for complex technical issues
We're here to help you succeed with your Galxe integration! 🚀
# Future works
Source: https://docs.galxe.com/identity/future-works/future-works
In this section, we list some future works that we can think of.
## Expanding to Mina ecosystem
Because of the swift progression in zero-knowledge proof technology, there exists an opportunity to expand the Galxe identity protocol into more ecosystems. Within this realm, Mina emerges as a paramount option. It is equipped with a proof system that can also run in user’s local devices, especially in web browsers, thereby enabling the privacy-preserving proof generation and on-chain proof verifications on the Mina protocol. Additionally, this proof system is distinguished by numerous benefits, such as the ability for make recursive proofs and verifications, and the potential to support more universally recognized signature algorithms, for instance, ECDSA.
Same as BabyZK, the verification can happen both off-chain (using SDK), and on-chain, by sending proofs to contracts on Mina protocol. Because that Mina protocol has native support for zero-knowledge verification, an gas-saving attestation design is considered to be redundant in this context. In another word, smart contracts on Mina protocol should be able to consume proofs directly with affordable gas.
For issuers, when issuing the same credential for the same identity using different stacks, they must request a proof of same identity commitment from the owner, because the output of poseidon hash under different curves are different.
## Verification stack: o1js
* **Curve**: **[Pasta Curves](https://o1-labs.github.io/proof-systems/specs/pasta.html?highlight=curves#pasta-curves)**. All the following algorithms are using this curve.
* **Hash**: Poseidon.
* **Digest:** The digest is derived from the Poseidon hash of `poseidon(header, signature metadata)` and `poseidon(body)`. Initially, the header and signature metadata are cohesively hashed, according to the canonical sequence of header fields followed by signature metadata fields. Subsequently, the fields within the body are hashed in the type definition order. Finally we take the Poseidon hash of the two hash values.
* **Signature**: EcDSA. Because EcDSA signature is not yet live on Mina mainnet (only available for zkApps), we may change the signature schema.
* **Identity commitment schema:** a 2-input poseidon hash of curve of two fields: `identity secret` and `internal nullifier` , in this specified order.
* **Circuit language**: o1js, a typescript-native SDK
* **Proof system**: Kimchi
# Galxe Identity Protocol
Source: https://docs.galxe.com/identity/introduction
Where Identity Meets Privacy, Where You Take Control

# Introduction
Galxe Identity Protocol proposes a cutting-edge system that gives our community complete control over their private data and identity, redefining the way credentials are issued and verified in the Web3 world.
What are credentials? Credentials live in our everyday life. They are proofs of eligibility in the form of a key, a certificate, a deed, a license, and more. Credentials of onchain activities include your contribution to a protocol’s liquidity pool, your on-chain voting history, and your participation in a Galxe Campaign, etc. These credentials not only aggregate your achievements and value but also represent who you are, your unique onchain identity.
All of your current behavioral data in Web2 can be credentials as well. Companies such as Google and Meta run algorithms on your credentials so that they can send you targeted advertisements. The problem is, however, you don’t own these data and you don’t get to decide what they are used for, who they’re shared with, and how you benefit from them.
[Galxe Identity Protocol](https://www.galxe.com/identity/) is a permissionless self-sovereign identity infrastructure. Powered by Zero-Knowledge Proof, you’ll be able to own, manage, and share verifiable credentials securely and privately. Galxe Identity Protocol also presents a diverse range of opportunities for builders to build Sybil prevention algorithms, reputation systems, credit systems, personal data markets, decentralized review systems, and beyond.
Why does this matter to you? First of all, your identity and private data become your assets, including your followers on social media, your avatars, your achievements in games, and more. You get to decide the when, what, and how for your data — because you truly OWN them. You won’t need a notary to prove your house belongs to you. You won’t need to send your whole bank statement to prove you have a certain amount of money. This might seem a little farfetched, but in a world where AIs are writing your emails and cars are driving you to places, this is the future, and it’s near.
# How It Works, the Technical Part
While this all sounds great, how does it actually work?
Galxe Identity Protocol aims to improve what Galxe currently offers and separate the functionality into individual and interdependent pieces. There are four major roles in Galxe Identity Protocol: Credential Holder, Issuer, Verifier, and Credential Type Designer. Within the current Galxe platform, Galxe designs and provides a variety of Credential Types for projects to utilize. Campaign owners then verify and issue the credentials to eligible participants, who become the Holders of those credentials.

At its core, Galxe Identity Protocol consists of a series of smart contracts to be deployed onchain and SDK tools that allow developers to build and use those contracts to issue or authenticate credentials offchain. A credential schema requires two parts: the context and the credential type. For example, the context is whether you’re over 21 years old, and the type is boolean (yes or no).
With its permissionless and decentralized nature, Galxe Identity Protocol constitutes chain-agnostic components catering to all roles to make the system sustainable.
1. Holders can selectively disclose requisite information for specific verification instances under a deterministic pseudonymous identity.
2. Issuers can generate revocable credentials and manage them on-chain.
3. Verifiers have the ability to specify a programmable trust schema, and by using the built-in identity nullifiers, they can use the protocol for various applications requiring access control, both on-chain and off-chain.
Galxe Identity Protocol further enhances verification efficiency by facilitating minting of soul-bound tokens (SBTs) based on typed credential and supporting no-code compositional verification.
If that’s too abstract, let’s take a closer look at some scenarios.
1. You are an active social media user. Your assets include your followers, the content you publish, and your data footprint. Instead of being exploited for targeted advertising, you can now choose to verify and disclose who you are and what you’re interested in.
2. You are a gamer and you just achieved a certain rank or beat a boss in a particular game. The gaming project can reward you in the game directly with a bounty, limited edition weapons, and more, after verifying the credentials. With Galxe Identity Protocol, your in-game achievements are owned and controlled by you, thus 100% authentic and private. You can choose to disclose these credentials to other games and advertisers in exchange for benefits.
3. You are over 21 years old living in the U.S. and you need to prove to an alcohol vendor that you’re old enough to make a purchase. Instead of showing them your ID, which discloses all the information including your name, address, eye color, you can show them a verified credential that proves you’re old enough.

Another major problem that Galxe Identity Protocol solves is the digital identity multiplicity problem. The nature of modern digital identities is multidimensional, that a person can have multiple different identities across different platforms. This phenomenon introduces a subtle challenge for designing a credential protocol: which identity should the issuer credential to? The design must allow a user to connect all identities in order to reveal or generate Zero-Knowledge Proofs against a comprehensive profile, while not leaking any privacy, e.g., the connections of accounts, to any other party.
If you’re interested in learning more about what Galxe Identity Protocol has to offer, here’s the whitepaper with all the information you’ll need.
# The Vision of Galxe Identity Protocol: Decentralizing Roles
Galxe Identity Protocol envisions breaking down the roles currently embodied by Galxe, enabling various independent entities to assume one or more of these roles. This decentralization allows for a more dynamic ecosystem that brings the Galxe experience beyond the core Galxe platform.
For example, third parties are invited to design their own credentials. Instead of being solely reliant on Galxe to introduce new credential types, third parties can step in to design and propose them. For instance, if there’s a demand for a “Threads” credential type, an external entity can design it. Once designed, Galxe or any other platform can opt to support and integrate these new credential types. This approach mirrors the flexibility seen in our current subgraph setup.

The design of Galxe Identity Protocol also provides more flexibility to role assumption, allowing other entities, including Galxe, to selectively take on roles based on the specific use case. For instance, Galxe might only play the role of an issuer for certain credentials, leaving the verification to another entity.
* **Scenario 1:** Galxe issues a credential. A gaming partner then verifies this credential and subsequently issues a reward directly from their platform or from a third-party like Steam.
* **Scenario 2:** Conversely, a gaming partner might issue a credential to a user directly or through Steam, who can then redeem a reward directly on Galxe.
# Why Zero-Knowledge Proof (ZKP)?
We’ve mentioned Zero Knowledge Proof quite a few times. Here’s why we believe and choose ZKP as the cryptographic method for Galxe Identity Protocol.
**Selective Disclosure:**
Imagine a gamer wants to join a gaming guild in a platform integrated with Galxe. The guild requires members to have achieved a specific rank in another game. With ZKPs, users can prove their achievements without revealing all their gameplay history or any other irrelevant stats. This ensures credential privacy.
**Proof with Anonymity:**
A user wants to participate in a special event on a platform, but the event requires participants to have a specific reputation score. With ZKPs, participants can prove they’re beyond the reputation threshold without revealing their identities or specific aspects that contributed to the score. Moreover, verifiers can use the nullifier in the proof to prevent double-spending. This addresses the challenge of data verification with anonymity.
**Efficiency and Security:**
As Galxe integrates with more platforms and supports more credential types, the demand for verification could skyrocket. ZKPs, especially zk-SNARKs, ensure the verification process to be as speedy and smooth, even with exponential growth in demand. For instance, if a user holds credentials from 50 different platforms, these credentials can be efficiently verified with any combination using ZKPs, avoiding significant computational burden.
Into the future, Galxe envisions a seamless integration, verification, and reward distribution process that is interoperable, private, and secure.
# Whitepaper
To view the whitepaper, please [visit this link](https://github.com/Galxe/protocol-whitepaper/blob/main/Galxe_Protocol_Whitepaper.pdf).
# Background
Source: https://docs.galxe.com/identity/introduction/background
The concept of self-sovereign identity (SSI), in which individuals have full control over their personal information used for verification purposes, has gained significant attention over the past decade, fueled by the advancements in blockchain technology and the pursuit of decentralization. In an era marked by ever-increasing digital identity inter-connectivity, the limitations of traditional models of identity management have become a critical concern. Methods that rely on centralized authorities and third-party intermediaries have faced significant challenges in terms of privacy, security, and sovereignty.
Over the past two years, [galxe.com](http://galxe.com/) has emerged as the leading user growth community within the Web3 ecosystem, relying extensively on credential-based systems for hosting marketing campaigns. During this period, our platform has facilitated the issuing of over one hundred million credentials to more than ten million users. At its peak, Galxe conducted over one million verification in a single day. Such extensive engagement has endowed us with firsthand experience and profound insights into the challenges associated with the existing solutions of verifiable credential and SSI, specifically regarding scalability, privacy, or the realization of self-sovereignty for users. While the [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) has defined the structure of verifiable credentials and pioneers like [Iden3](https://iden3.io/) and [Ethereum Attestation Service](https://attest.sh/) (EAS) have launched services in production, widespread adoption is still in its early stages and has not been fully realized.
In response to the challenges we faced on [galxe.com](http://galxe.com/), we have designed Galxe Identity Protocol, a SSI service that utilizes verifiable credentials, powered by zero-knowledge proof mechanisms. The architecture of this protocol is meticulously crafted to be **privacy-first, user-friendly, scale-able,** and **future-proofing**. Galxe identity protocol allows credential holders to selectively reveal requisite information in form of zero-knowledge proofs, while maintaining their pseudonyms. Proofs can be generated within seconds by Galxe identity vault in browsers or mobile devices, and verifications can happen on-chain at affordable costs. The protocol uses a flexible identity commitment schema to address the issue of digital identity multiplicity, so that nullifiers of proofs are deterministic and can be utilized by verifiers without introducing an extra layer of trust. This design ensures the privacy and non-traceability of the underlying identity, even in scenarios where collusion between issuers and verifiers occurs and verification activities are publicly disclosed, e.g. on-chain verification. In addition to holders, issuers and verifiers can leverage our ease-of-use Software Development Kits (SDKs) to apply ZKP without the necessity of understanding ZKP. Moreover, the typed credential design allows most issuers to create new credentials in a no-code fashion, and the unique aggregation mechanism further enhances verification efficiency by facilitating minting of a soul-bound token (SBT) or on-chain attestations (like EAS) for reduced cost verification in the future. Holders are not required to register for a global ID or reveal any commitment on-chain, and lazy registration is supported for issuers. The protocol promotes the use of non-revocable credentials with expiration for scalability, while also supporting revocable credentials on-chain. In recognition of the rapid-evolving nature of of ZKP technology, the protocol adopts a modular verification stack design, making it future-proofing.
The first verification stack is using groth16, a Zero-Knowledge Succinct Non-Interactive Argument of Knowledge (zk-SNARK) system, for efficient proof generation and lower cost on-chain verification. It is implemented using circom and snarkjs. New verification stack, based on different proof systems like o1.js, can be added with full backward compatibility. Our open design also empower us to swiftly integrate other services in the ZKP ecosystem, e.g., cheap on-chain proof verification through proof aggregation, provided by Nebra’s Universal Proof Aggregation.
# Case Studies
Source: https://docs.galxe.com/identity/introduction/case-studies
# On-chain NFT drop for early users using Galxe identity protocol
The Galxe identity protocol offers a solution for services that require identity-based access control, just like a bouncer at a club. To demonstrate its application, let's consider an on-chain NFT drop scenario.
**Scenario:**
A decentralized exchange (DEX) project on EVM chains, named *Alpha*, intends to reward its early supporters (angel users) with a unique on-chain NFT drop. The criteria for qualifying as an angel user are:
1. Following their official Twitter account (X) within the first 30 days post-launch. Given that Alpha launched on 01/01/2021, the cut-off date is 01/31/2021.
2. The user's nationality isn't on the disallowed list.
3. For every \$1000 trading volume, the user qualifies for one NFT drop.
Instead of creating an application that mandates users to link their EVM address, Twitter, and undergo KYC (potentially compromising privacy), Alpha can utilize the the protocol for a privacy-centric approach:
1. **Issue trading volume credentials**: Alpha becomes a credential issuer, providing scalar-typed credentials under the context "Project Alpha trading volume" to its users. Users must submit an identity commitment to Alpha, either on-chain via a registry contract based on **`msg.sender`** or off-chain through ECDSA signatures, to receive the credential. Alpha ensures one EVM address corresponds to a single identity commitment, as required by the protocol.
2. **Select 3rd-party credentials issuers**: Alpha collaborates with two reputable credential issuers to verify user’s Twitter follows and user nationalities. We assume that Twitter follow credentials have two claims in its body: followed account ID and verification date, from issuer *deSocial*. As for nationality, we assume that the issuer, *DeKYC*, provides passport-type credentials which includes a claim about the holder’s nationality.
3. **Deploy NFT drop smart contract**: Alpha deploys a smart contract that rewards NFTs based on trading volume to any address providing valid zero-knowledge proofs with unused nullifiers. The external nullifier is set to **`0x18d...`**, derived from the hash of "Alpha angel user NFT drop".
The smart contract checks the proofs against:
**General requirements:**
* The revealed identity specified in proof, backed by the fact that only the credential holder knows secrets of identity commitments, must match the **`msg.sender`**.
* The external nullifier is **`0x18d...`**.
* Nullifiers are either unused or associated with other addresses.
**Credential-specific requirements**:
1. **Twitter Follow**: The zero-knowledge proof must confirm the followed account is Alpha and the verification date is before 01/31/2021.
2. **Passport**: The proof should list countries that don't match the user's nationality, and the list is a super set to the Alpha’s disallow list.
3. **Trading Volume**: The proof must show the lower bound of the trading volume, determining the number of NFTs a user can claim. To incentivize trading, unlike the above two credentials, this credential isn't voided but linked to an EVM address for future volume updates.
| Credential | Type | Context | Public inputs | On-chain verification | Post-verification actions |
| -------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Twitter follow | Custom, two claims:
1. Followed account ID.
2. Verification date. | Simple non-revocable twitter follow credentials with verification date, issued by DeSocial. | 1. Equality of followed account ID v.s. “Alpha”.
2. Upper bound of verification date.
3. External nullifier and nullifier A.
4. Revealing identity is X. | 1. Equality is true.
2. Upper bound is before 01/31/2021.
3. External nullifier is 0x18d...
4. X is msg.sender.
5. A has not been marked as used. | Mark nullifier A as used for twitter credentials. |
| Passport | Custom, containing a claim of nationality. | DeKYC’s AI-power KYC solution. | 1. Equalities of nationality v.s. a list of countries.
2. External nullifier and nullifier B.
3. Revealing identity is X. | 1. Equalities are all false, and the list of countries is a superset of the disallow list.
2. External nullifier is 0x18d...
3. X is msg.sender
4. B has not been marked as used. | Mark nullifier B as used for passport credentials. |
| Trading volume | Scalar (a basic credential type shipped) | Project Alpha trading volume | 1. Lower bound of trading volume.
2. External nullifier and nullifier C.
3. Revealing identity is X. | 1. External nullifier is 0x18d...
2. X is msg.sender.
3. C has not been binded yet, or binded with msg.sender | Bind C with msg.sender, as used for trading volume credentials, and set the number of available NFTs to mint to be lower\_bound\_volume / 1000 |
Once preparations for Project Alpha are complete, we can focus on the user experience. The user workflow is streamlined: collecting credentials and generating proofs for verification. All these steps can be effortlessly executed using the **Galxe Identity Vault**, a local application compatible with both browsers and mobile devices.
1. **Credential Collection**: Users are required to gather three distinct credentials from separate issuers. If a user has not previously requested credentials from these issuers, they would need to set up three unique identity commitments. The Galxe Identity Vault automates this process, ensuring that all confidential information remains safeguarded by the user's password.
1. **Twitter follow**: Visit *DeSocial’s* website or app, connect with Galxe Identity Vault\*, and\* potentially do an OAuth login with your twitter account to verify the follow status. Then *DeSocial* will request a identity commitment from the connected Galxe identity vault, and delivery the credential directly to the vault.
2. **Passport**: By accessing *DeKYC's* platform, users may pay a service fee for KYC verification and credential issuance, then DeKYC will follow a process analogous to the one mentioned above.
3. **Trading Volume:** Within Project Alpha's application, users can directly request a trading volume credential, again following a similar procedure.
2. **Proof Generation**: With the three credentials secured, users can effortlessly produce zero-knowledge proofs using the Galxe identity vault. The intricate technical details of generating these proofs remain hidden from users. Instead, Project Alpha forwards statements to be proved directly to the vault. The vault then displays the information set to be disclosed, such as "your nationality differs from countries A, B, C..." or "Your trading volume exceeds XXX", seeking user confirmation. Upon approval, the proofs are generated and sent to the smart contract for NFT minting.
It's worth noting that while this process is hosted on-chain, it can also be executed off-chain in a centralized manner.
**Security Analysis:**
1. **Identity Linkage Protection**: The protocol ensures that users' identities across various platforms remain concealed. These identities are interconnected using different identity commitments and the revealed identity. Importantly, even if multiple issuers were to collude, they will not be able to correlate a user's identity across different platforms, as long as users follow the best practice of using different identity commitments for each issuer.
2. **Pseudonymous Claims**: Users have the flexibility to claim NFTs under a pseudonym. This ensures that their trading address on the DEX remains separate from their NFT ownership, bolstering privacy. As a practical implication, a user can sell their NFTs on a KYC-mandated marketplace without the fear of their KYC data being associated with their trading activities on the DEX.
3. **Double-spending Prevention**: Nullifiers ensure credentials cannot be used more than once. This ensures that each angel user can only claim their rightful amount of NFTs.
4. **Minimal Data Exposure**: The protocol is designed to disclose only the bare minimum data, thereby reducing the risk of privacy breaches, such as birthday attacks. For instance:
* For the Twitter follow date, users disclose the an upper bound of verification date, instead of a precise date. All angel users can standardize it to 01/31/2021.
* Regarding nationality, the protocol doesn't directly reveal the country. Instead, it provides a list of countries that don't match the user's nationality, which is theoretically the least revealing method.
* For trading volume, a lower bound is used in place of the precise volume, which can be easily used to identity an user. The lower bound can be adjusted to any legit N \* 1000, based on the number of NFTs a user could and intend to mint.
# Concepts
Source: https://docs.galxe.com/identity/introduction/concepts
In this section, we provide a comprehensive overview of preliminary concepts, with a particular emphasis on notations used by this paper. We assume that readers are familiar with cryptographic concepts, including hash functions, asymmetric cryptography, digital signatures, sparse merkle trees, and basic understanding of zero-knowledge proofs.
### Digital identity multiplicity problem
The term *digital identity multiplicity* emphasizes the multidimensional nature of modern digital identities, that a person can have multiple different identities across different platforms. For example, it is not uncommon that a user uses different nicknames, handles, and cryptographic IDs (namely addresses) for different platforms. A user might be called *`MightyKitty`* on twitter, while being *`BraveBarbie`* on discord, or uses address `0x7f7f7…abc` on EVM-compatible blockchains.
The phenomenon introduces a subtle challenge for designing a credential protocol: under what identity, should the issuer credential to? The design must allow a user to connect all his owned identities in order to reveal or generate zero-knowledge proofs against a comprehensive profile, while not leaking any privacy, e.g., the connections of accounts, to any other party.
One straightforward solution is to issue credentials under the ID of the domain that the issuer controls. That is, a credential showing that the user *`MightyKitty`* has more than 1000 Twitter followers, should be issued to the *`MightyKitty`*. However, this implementation can hinder the interoperability of credentials. When using credentials outside of the issuer’s domain, the user has to prove that he is the ID shown on the credential. This process can be done through a 3rd party, which introduces another layer of trust, or the user has to reveal his ID to the verifier, sacrificing privacy. Another choice is using a global identifier schema, where each user is assigned to a globally unique identifier and issuers shall create credentials to that identifier. However, when issuers collude, a unique identifier can be used to track down footprints of the user behind, by linking together different identities from different issuers.
We proposes an innovative schema that, by embedding identity commitments into credentials, allows a user to harness his credentials from different platforms, while preserving his privacy.
### Nullifier
In the context of zero-knowledge proof cryptography, a nullifier is a value that prevents double-spending, without revealing which resource is being spent. Essentially, it is a value that 'nullifies' (voids) the underlying resource in a privacy-preserving way. It plays a critical role in the applicability of zero-knowledge proof methods to practical applications. The lack of the ability to generate nullifiers with proofs compromises the verifier's ability to ascertain if a proof has been previously utilized. To draw an analogy, one may envision a scenario where a huge group of people is permitted entry into a concert event, but using a single ticket meant for only one person.
### Identity commitment
An identity commitment is a public value, hiding two secret values: a secret identity and an internal nullifier. Both secret values are known only by the credential holder, while identity commitment can be public. In Galxe identity protocol, conceptually, identity secrets will be used by holders to prove the ownership of credentials, and internal nullifiers will be used, together with external nullifiers, to generate deterministic nullifiers per each verification.
Similar to [Semaphore protocol](https://semaphore.appliedzkp.org/docs/guides/identities), our protocol constructs identity commitment in the same simple way. It is a Poseidon hash of two secrets. Note that the order of two secrets is fixed when used as the inputs to the hash function. The first one is the identity and the second one is the internal nullifier, so that nullifiers and secrets can be distinguished in a zero-knowledge proof.
Compared with digital signatures, the power of identity commitment is actually smaller. You cannot use it for authentication without using a zero-knowledge proof, and secret values will have to be the inputs to the prover, unlike signatures where only public keys and signatures are required. However, this disadvantage can help to limit impersonation and fake profiles. For a credential, identity secrets cannot be shared without permanently sharing the ownership, while signatures can be shared with limited costs: one can temporarily transfer or lease the ownership of a credential to someone else, until the signature expires.
### Verification stack
A verification stack is a set of instantiations of cryptographic algorithms that will be applied during credential issuance, proof generation and verification. Because the domain of zero-knowledge proof technology is witnessing a meteoric rise, with innovative techniques being invented rapidly, alongside the consistent refinement of implementations, the protocol is designed with a vision for future adaptability. The design de-couples the signature and verification schema from the core protocol, allowing versatile use cases and smooth upgrades.
The initial version of Galxe identity protocol will come with one simple yet powerful verification stack called ‘BabyZK’. It is a production-ready full-feature zero-knowledge tech stack that supports ultimate privacy protection, that can be used even publicly on blockchains, like Ethereum.
### Credential schema
In Galxe identity protocol, credential schemas are defined by the two fields on credentials: **type** and **context**. Like types in programming languages, credential types are structs, specifying the list of typed claims. A type will be associated with a set of zero-knowledge circuits and verification parameters published on-chain. On the other hand, a credential context is used to construct a concrete instantiation from a credential type. Together, they form a credential schema, consisting of typed claims under a specific context. For example, assuming there is (there actually will be) a simple credential type with one unsigned integer field and we call this type ‘scalar’, different schemas can leverage this same type by linking different contexts, e.g., the number of loyalty points, the highest rank achieved in a game, or date of birthday expressed in UNIX timestamp. These credential schemas can all use the zero-knowledge circuits that have been created for the scalar type. This advantage allows issuers, holders, and verifiers to apply zero-knowledge proofs without writing any code.
### Parametric on-chain attestation by aggregating public inputs
For on-chain verifications, users can mint an attestation that caches the revealed facts with auto aggregation. For each pair of `(type, context)` and an `issuer`, there will be an attestation collection. Every attestation has a unique token id, which is the nullifier generated by the owner, and its properties represent some facts of the owner. The facts are automatically aggregated based on all past information revealed, during on-chain verification. Because fields are typed, aggregations are also type-aware. Taking an unsigned integer field as an example, its lower bound and upper bound that have been checked will be stored. For example, if there were two proofs that one says `height > 100 && height < 150`, and the other says `height < 123`, the attestation of height will be `lower_bound: 101` and `upper_bound: 122`. Note that the attestation will not leak any extra information about the owner, because when the verification happened, those facts have already been revealed publicly, at the owner’s will. For revocable credentials, the root hash of sparse merkle tree of revoked credentials that has been used during proof will be cached.
This attestation offers the potential for future verification at a reduced computational cost. On Ethereum, a ZK-SNARK verification of Groth16 on BabyJubjub curve generally costs around 300k gas. In contrast, querying an attestation property necessitates only a few thousand units. Because activities under the same pseudonym of the attestation will be public, protocol leaves the freedom to choose between the highest level of privacy and gas efficiency to verifiers and holders.
# Overview
Source: https://docs.galxe.com/identity/introduction/overview
One of the most important functions of digital credentials is their verifiability through cryptographic methods. Although the verifier still needs to trust the credential issuer, this functionality obviates the necessity for verifiers to interact with the data sources. Moreover, it empowers the holder of credentials with the complete ownership of the data, thereby endowing them with the discretion to decide where, when, who and what to share.
The Galxe identity protocol defines the ‘how’. The protocol provides a set of ease-of-use SDKs, smart contracts and identity vault applications, hoping to bring the state-of-art SSI service to millions of users. Before jumping into the technical details of the protocol, we will give an overview of preliminary concepts and explain the capabilities and responsibilities of each role of the ecosystem. At the end, we will give an example of leveraging the protocol to run an on-chain NFT drop for angel users, where the security of application and user privacies are both protected.
# Roles
Source: https://docs.galxe.com/identity/introduction/roles
The protocol incorporates four main roles, each contributing uniquely to the protocol's functioning. This section will give a brief introduction to their capabilities and responsibilities.
### Holder
The Holder role is the centerpiece of the whole ecosystem: the individual possessing verifiable credentials. Holders do not need to register anything on-chain and the ownership of a credential is controlled by identity commitments constructed from secrets that are only known by their holders. In the Galxe identity protocol, holders maintain total control over their digital identity by storing credentials in Galxe identity vault, an open-source application that runs on holders’ local devices, e.g. browser, and native applications. Holders use the vault to manage different identity commitments for different issuers, and generate zero-knowledge proofs for verification based on owned credentials. By using ZKP, holders have the ability to reveal only requisite data under a deterministic and pseudonymous identity.
### Issuer
Issuers create verifiable credentials to holders by using digital signatures to endorse claims about the holder. In our design, issuers do not need to know any extra information of a holder, except for the identity commitment, which can be considered as a random number. Any identity can issue non-revocable credentials to others without on-chain registration. However, for revocable credentials, issuers must be registered on-chain to manage credential validity by publishing the root hash of sparse merkle tree of revoked credentials. Moreover, public keys used for signing need to be registered on-chain to be linked to their issuers.
Issuers can use auxiliary contracts, such as Domain Name System Security Extensions (DNSSEC) verification, email verification and GAL staking contracts to enhance their perceived trustworthiness and credibility. Verifiers can leverage these records for setting up a dynamic trust schema. For example, instead of trusting credentials signed by a specific key, verifiers can program a policy that trusts issuers with DNSSEC verification of a specific domain, with some specific corp email ownership, or issuers with enough GAL staking.
Issuers must maintain a 1-to-1 mapping from users of the domain to identity commitments. The identity secret part can be changed with a zero-knowledge proof that ensures the internal nullifier remains the same.
### Verifier
The verifier is the role that has the least dependence with other roles of the ecosystem. They are usually applications of gated services, allowing access only if the identities meet some specific requirements, like bouncers at bars. To host a verification, verifiers need to pick issuers that they can trust via a programmable trust schema, and verification requirements of credentials to be checked. Verifiers can use the protocol SDK to generate verification requirements that holders can use for generating proofs. To verify a proof, verifiers need to fetch verification key based on the type of the credential from blockchain, and check revocation status if there is any proof of revocable credentials. For each verification, verifiers should use a unique external nullifier and keep tracking of used nullifiers to prevent double-spending.
### Credential type designer
Credential designers propose new types of credentials to the community, specified in a domain-specific language (DSL) of the protocol. These individuals, typically community contributors, actively participate in shaping the ecosystem of evolving needs and requirements, by introducing innovative and diverse credential types. With Galxe identity protocol SDK, designers turn the type specification written in DSL into automatically generated zero-knowledge proof circuits, smart contracts proposed. Depending on the verification stack, type designer may need to hold a decentralized trust set up ceremony and publish the proof key to permanent storages.
Designers must also provide a detailed specification of in-depth description of the credential type, outlining its purpose, intended use cases, and the specific attributes and fields it contains. These specifications clarify the semantic meaning of each field, define any restrictions or requirements associated with the credential, and provide guidelines for issuing and verification. The specifications ensure a shared understanding among ecosystem participants regarding the purpose and usage of the proposed credential type.
Although it is a permission-less process to introduce new types to the ecosystem, the protocol employs a governance framework to facilitate decision-making regarding inclusion of new credential types into official core types with long term support. The community, comprising users, developers, and other stakeholders, actively participates in the evaluation and acceptance process. Through transparent discussions and GAL voting mechanisms, the community collectively determines which proposed credential types are incorporated into the official type.
# Contracts
Source: https://docs.galxe.com/identity/resources/contracts
Source code for our smart contracts can be found [here](https://github.com/Galxe/identity-protocol/tree/main/packages/evm-contracts).
Cross chain contract address (Gravity Alpha Mainnet, Ethereum mainnet, Ethereum Sepolia testnet, BNB Chain, Polygon):
* Type Registry: 0x77dA3Cf4418009D171B4963db815Ca46d6F2E79D
* Context Registry: 0x42D6444840842F0484C1624899c9a3E835738592
* Issuer Registry: 0xc4525dA874A6A3877db65e37f21eEc0b41ef9877
* BabyzkDefaultPublicSignalGetter: 0x1418b5e79eE53396dE4a454d78DF2ab522CE24CC
* BabyzkStatefulVerifier: 0xF3D3404eb75D076Ab8A0F728C7FAA3c0A5e6549F
On Sepolia only:
Once [NEBRA](http://nebra.one) goes mainnet, we will deploy this contract to
the corresponding chains too.
* AggregatedBabyzkStatefulVerifier: 0x217F3a88653F84C26ce159BC5417d9A54e6eA7F1
# TypeScript SDK
Source: https://docs.galxe.com/identity/sdk
## About the SDK
The Galxe Identity Protocol TypeScript SDK empowers developers to:
* Design new ZK credential types using our domain-specific language (Type DSL), without requiring any knowledge of zero-knowledge proofs.
* Issue ZKP-powered credentials.
* Generate zero-knowledge proofs.
* Interact with on-chain contracts for tasks such as issuer registration, context registration, and proof verification.
* Most of the gadgets you would need, if not everything.
## Code Repository
All source code can be found in our monorepo on GitHub: [Galxe Identity Protocol](https://github.com/Galxe/identity-protocol).
## SDK Installation
Install the SDK using npm, Yarn, or pnpm with the following commands:
* **npm**
```bash theme={null}
npm install @galxe-identity-protocol/sdk
```
* **pnpm**
```bash theme={null}
pnpm add @galxe-identity-protocol/sdk
```
* **Yarn**
```bash theme={null}
yarn add @galxe-identity-protocol/sdk
```
## EVM Contracts in Solidity
For developers aiming to integrate or directly interact with our EVM contracts, refer to the code and documentation available here: [EVM Contracts](https://github.com/Galxe/identity-protocol/tree/main/packages/evm-contracts).
## Issuer gRPC Service
For those planning to serve as issuers, we provide a Node.js (written in TypeScript) gRPC service and a Dockerfile. This can be deployed as a microservice in your infrastructure to facilitate credential issuance to users. Learn more and access the service here: [Issuer Service](https://github.com/Galxe/identity-protocol/tree/main/apps/issuer).
# Credential Format
Source: https://docs.galxe.com/identity/specification/credential-format
A credential is made from header, body, an array of signatures and attachments. This design allows a credential to be endorsed by multiple signatures from different issuers, or using different verification stacks. Credentials are primarily stored and presented to holders in JSON format, for readability, while other formats like YAML, XML can also be supported. Note the formats of storing and showing the credential are not related to how the digest (i.e., the hash value) is computed, and will not affect zero-knowledge proof generation. The digest algorithm is determined by the verification stack and it can evolve without upgrading the main protocol.
```
+----------------------------------------+
Header | Version, Type, Context, ID |
+----------------------------------------+
Body | (Field)* |
+----------------------------------------+
| Metadata | Signature |
Signature(s) |----------------------------------------|
| ...more signatures... |
+----------------------------------------+
Attachments | Signer ID, Public key.... |
+----------------------------------------+
```
```json theme={null}
{
"header": {
"version": "1",
"type": "778",
"context": "666",
"id": "9"
},
"body": {
"token_balance": "100",
"birthday": "200",
"status": {
"str": "enabled",
"value": "2"
},
"followed": "true"
},
"signatures": [sig1, sig2...]
}
```
```json theme={null}
{
"metadata": {
"verification_stack": 1,
"signature_id": "999",
"expired_at": "100",
"identity_commitment": "123",
"issuer_id": "456",
"chain_id": "0",
"public_key": "public key bytes"
},
"signature": "signature bytes"
}
```
### Header
Header contains the common fields that all every credential must have.
* **Version** (uint8) : The version of protocol. Currently, the only supported version is 1.
* **Type** (uint160) : The type ID this credential, specifying the order and type of the claims in the body. This value will be a public signal of a proof.
* **Context** (uint160) : The context ID of the credential. This context ID needs to be registered on-chain before using it. Issuers are allowed to re-use the context created by others. Context IDs are computed by taking the 160 least significant bits of the keccak256 hash of the context string. Optionally, the issue can attach the original context string in the attachments section for better readability. This value will be a public signal of a proof.
* **ID** (uint248) : An identifier of holder. For example, an EVM/Bitcoin/Solana/Cosmos/Mina address, a X (Twitter) handle, or a Discord handle. If the original identity is a string, issuer must convert it to an integer value, by taking the 248 least significant bits of the output of some collision-resistant hash function, or ways that can guarantee the 1-to-1 mapping from the original handle to the ID. For example, 160-bit EVM address can be directly used as IDs. This value does not need to be registered on-chain. It will not be a public signal of a proof. Instead, the proof will contains a equality check result that shows the ID equals or not equals to some ID.
For example, to create a credential of the loyalty points, that a [Galxe.com](http://Galxe.com) user has earned in the Galxe space, assuming that we have registered the context “Galxe.com loyalty points” on-chain and the context ID is `0xdeadbeef....`, when the user’s Galxe ID is `123123` , Here is an example header. Note that Its type ID is 2, meaning that it is using the primitive credential type containing just one scalar value.
```json theme={null}
"header": {
"version": "1",
"type": "2",
"context": "0xdeadbeef..",
"id": "123123"
}
```
### Body
The body part stores all claim values, corresponding to the claim types declared in the credential type. Below is an example of credential body and its type definition. Note that the `status` claim value stores not only the hash value, but also the original value. This is because that the claim declaration specify that the hash algorithm is user-defined ( `c`), storing both values is mandatory by protocol’s specification.
```json theme={null}
"body": {
"token_balance": "100",
"birthday": "200",
"status": {
"str": "enabled",
"value": "2"
},
"followed": "true"
},
```
```
token_balance:uint<256>;
birthday:uint<64>;
status:prop<32,c,1>;
followed:bool;
```
### Signature
The signature part of a credential is an array of pairs of metadata and signature, allowing one credential to have multiple signatures. Although the format of a signature is specified by the verification stack used by the issuer, all signatures shares a common metadata structure.
**Signed signature metadata**
* **verification\_stack\_id** (uint8): an ID of verification stack used for this credential.
* **signature\_id** (uint248): the id of this signature that will be used to manage revocation. This value will never be exported as a public value for user’s privacy. It will only be used in the circuit when proving that the credential is not revoked, if required.
* **expiration** (uint64): the UNIX timestamp of when the credential will be expired. This field is mandatory and you can fill-in an `UINT64_MAX` if the credential never expires.
* **identity\_commitment** (uint256): a field serves as the identity commitment for zero-knowledge proofs. The algorithm of computing the value is depending the chosen verification stack.
Identity commitment will be used as the key to the power of creating a link from an identity to another one, e.g., from a twitter handle to an EVM address. At verification, a holder must generate a proof that he is the actual owner of the credential, by showing that he knows the secrets behind the commitment, and output a number representing the pseudonymous identity the verifier will see. Thus, the verifier is assured that the verification originates from the holder and confirms the holder's identity as the entity communicating with the verifier in that session.
Note that `issuer_id` is not part of the signed metadata. In our design, the `issuer_id` is intentionally omitted. This approach prevents the embedding of trust relationships between the issuer and public keys within the credential, because the verification of a public key trustworthiness can only occur externally to the zero-knowledge proof circuit, as it involves stateful checks beyond cryptographic validation. This simplification eliminates the redundancy of including an `issuer_id` for zk proof generation. Furthermore, this flexibility enhances the system’s scalability and the fluidity of trust relationships, thereby maintaining the simplicity of the credential's structure while accommodating a dynamic network of trust.
**Unsigned signature metadata**
In the unsigned signature part, there are three mandatory fields: **`issuer_id`, `chain_id`** and **`public_key`**. They do not require explicit signing, because the issuer's signature inherently implies the public key value, and issuer\_id and chain\_id should not be signed and fixed.
* **issuer\_id** (uint248): Represents the unique identifier of the issuer.
* **chain\_id** (uint64): Represents the ID of the primary chain that the issuer was registered. Because the protocol is chain-agnostic and an issuer can register themselves in different chains using a consistent issuer\_id, this primary chain ID is only a suggestion from issuer to verifier about where to check the public key status and revocable credential state. Note that although chain id may a 256-bit value, we do not support chain id larger than uint64\_max.
* **public\_key** (specific to the verification stack): Contains public keys essential for signature validation without querying it from the network.
* Additional fields as deemed necessary by the issuer.
### Attachments
The "attachments" section houses values that are external to the main body of the credential. It means that these values are not authenticated (or *signed*) by the issuer by default. However, issuers have the freedom to add an signature attachment that signs all the other attached fields, using a preferred signature algorithm. The protocol do have any specification for this but may introduce one in the future.
Issuers have the flexibility to introduce any arbitrary fields to this section. For instance, an issuer could provide a passport credential accompanied by a PNG photo. In such a case, issuer can place the hash of the photo in the credential body, while the actual binary data of the image would reside in the attachments.
### Proof
Credential holders can generate zero-knowledge proofs to selectively disclose specific pieces of information on credentials. Regardless of the chosen verification stack, every proof consists of two main components: a proof and some public inputs. The structure and representation of a proof is varying by the verification stack. There are two types of public inputs: intrinsic public signals and user-defined signals. Intrinsic signals must be the first 8 or 9 signals (depending on if it is revocable) of the public input array. The protocol mandates the sequence of intrinsic signals as described below:
1. **out\_type** (uint160): The type ID.
2. **out\_context** (uint160): The context ID.
3. **out\_nullifier** (uint256): A value derived from both `internal_nullifier` and `external_nullifier`. When using the babyzk verification stack, this value is computed as `poseidon(internal_nullifier, external_nullifier)`.
4. **out\_external\_nullifier** (uint160): The external nullifier used to generate the proof.
5. **out\_reveal\_identity** (uint256): The identity endorsed by the credential holder. Verifiers are obliged to ensure this value aligns with the session user's identity. For instance, for on-chain verification on EVMs, this value should be the direct caller, represented by **`msg.sender`**, or indirectly be authenticated through an EIP-712 signature.
6. **out\_expiration\_lb** (uint64): This signal delineates the lower boundary of the credential's expiration date.
7. **out\_key\_id** (uint256): Represents the hash of the public key that authenticated the credential.
8. **out\_id\_equals\_to** (uint256): This field confirms the equality of the ID field. It adopts a compressed schema similar to `prop<248, c, 1>`. Here, the least significant bit designates equality, while its \[249..1] bits convey the value that underwent comparison.
9. **(optional) out\_sig\_revocation\_smt\_root** (uint256): Only if the credential is revocable, there will be this intrinsic public signal, representing the hash of the root of the sparse merkle tree used provided during proof generation.
10. Public inputs introduced by claims in the body will start from here.
```json theme={null}
{
"out_type": "778",
"out_context": "666",
"out_nullifier": "20587068051456727584720549518481563004145412893468610943364726469406950307723",
"out_external_nullifier": "20565030651454249290584727781400485209601570980842971037547488913190033044629",
"out_reveal_identity": "0xdeadbeef",
"out_expiration_lb": "99",
"out_key_id": "1743582416365651167392966598529843347617363862106697818328310770809664607117",
"out_id_equals_to": "19",
"out_sig_revocation_smt_root": "1243904711429961858774220647610724273798918457991486031567244100767259239747",
"out_token_balance_lb_msb": "0",
"out_token_balance_lb_lsb": "50",
"out_token_balance_ub_msb": "0",
"out_token_balance_ub_lsb": "101",
"out_birthday_lb": "199",
"out_birthday_ub": "201",
"out_status_eq0": "6",
"out_status_eq1": "8",
"out_followed": "0"
}
```
# Overview
Source: https://docs.galxe.com/identity/specification/overview
The protocol specification covers the domain-specific language (DSL) for definition of credential types, format of credentials, components and standard workflows throughout the lifecycle of credentials. Designed to be minimalism and future-proofing, the protocol isolates rapid-changing zero-knowledge proof technology from the core elements of a credential, using the modular verification stack design. For implementations that are specified by the chosen verification stack, we use BabyZK stack as an example for illustration.
# Primitive Types
Source: https://docs.galxe.com/identity/specification/primitive-types
# Built-in primitive types
Issuers can start to issue credentials of these primitives types without going through the type creation process.
Based on Galxe’s experience, these types should cover a large portion of common
use cases.
| Type ID | Name | Description | Definition | Example |
| ------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | Unit | The simplest credential type that does not contains any field. Owning a credential of this type means that the owner, indicated by the ID in header, is endorsed by the issuer for the context. | empty | 1. Have you ever been followed by Elon Musk.
2. Have you ever made any donation to Wikipedia.
3. Have you ever been a LP for Uniswap V2 before 2021. |
| 2 | Boolean | A credential with a bool claim. Comparing with Unit type, theoretically the set has two values instead of one. A practical difference is that Boolean type gives the owner the ability to choose to hide or reveal the value in the proof. There are some use cases, but in most cases, the Unit type is preferred. | `val:bool;` | Do you have an early supporter role in Galxe’s discord?
Since Galxe only issues credentials of this context to its guild member, owner can choose to reveal this value, showing that he is an early supporter, or without revealing the value, proving that he is at least a member of the guild. |
| 3 | Scalar | A credential with an unsigned integer claim, 248-bit. Unless 256-bit range is necessary, this type is recommended for credentials storing an unsigned integer value. | `val:uint<248>;` | 1. Holder’s loyalty points of some brand.
2. UNIX Timestamp of the holder’s first transaction on Ethereum.
3. ERC20 token balance on height 1000, when representing the token’s total\_supply \* decimals requires less than 248 bits. |
| 4 | Scalar256 | A credential with an 256-bit unsigned integer claim. Note that due to the scalar field size limit in some verification stack (including babyzk), the output signal of a 256-bit value will represented as two public inputs, making on-chain verification higher than the Scalar type. | `val:uint<256>;` | 1. ERC20 token balance, where the ERC20 token balance need the full 256-bit encoding. |
| 5 | Property | A credential with a 248-bit property claim, using user-defined hash algorithm, with 1 equality check. | `val:prop<248,c,1>;` | 1. Name of holder’s first pet.
2. Holder’s first name on passport. |
# Artifacts
Artifacts required to generate and verify proofs can be found at the following IPFS location:
| Type Name | IPFS |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Unit | [https://ipfs.io/ipfs/QmX8dx6onZornDd5wsM2raWDz1prRrjLcrNwgZHWonYHvw](https://ipfs.io/ipfs/QmX8dx6onZornDd5wsM2raWDz1prRrjLcrNwgZHWonYHvw) |
| Boolean | [https://ipfs.io/ipfs/QmZQBtQ8nxcUM6fLgG4NrFkgmZwpjgcqPz8PQwgvRbpNQK](https://ipfs.io/ipfs/QmZQBtQ8nxcUM6fLgG4NrFkgmZwpjgcqPz8PQwgvRbpNQK) |
| Scalar | [https://ipfs.io/ipfs/QmPABvgq3Rnu8jqMjXx2HhHAY9h9EL2Q2ZizAUZwVFuNfn](https://ipfs.io/ipfs/QmPABvgq3Rnu8jqMjXx2HhHAY9h9EL2Q2ZizAUZwVFuNfn) |
| Scalar256 | [https://ipfs.io/ipfs/QmRUR9uyzJ9fL9SodKEB2yA43aez3axHJH9m3Myu8nsv4o](https://ipfs.io/ipfs/QmRUR9uyzJ9fL9SodKEB2yA43aez3axHJH9m3Myu8nsv4o) |
| Property | [https://ipfs.io/ipfs/QmUv7qrsaaFFUDTouNCRQ8SF6B7UewQGNpANBFuqh6vdw3](https://ipfs.io/ipfs/QmUv7qrsaaFFUDTouNCRQ8SF6B7UewQGNpANBFuqh6vdw3) |
Inside each file you will find corresponding resource CIDs for circom file, verifier solidity code, verification key, wasm, and zkey. e.g. here is the resource files for type "unit"
| File | IPFS |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| circom\_uri | [https://ipfs.io/ipfs/QmW4SgG4pDDLyFLy7V12QxMSx5X7tAqyeA4kgEFR1oURba/circuit.circom](https://ipfs.io/ipfs/QmW4SgG4pDDLyFLy7V12QxMSx5X7tAqyeA4kgEFR1oURba/circuit.circom) |
| verifier\_uri | [https://ipfs.io/ipfs/QmW4SgG4pDDLyFLy7V12QxMSx5X7tAqyeA4kgEFR1oURba/verifier.sol](https://ipfs.io/ipfs/QmW4SgG4pDDLyFLy7V12QxMSx5X7tAqyeA4kgEFR1oURba/verifier.sol) |
| vkey\_uri | [https://ipfs.io/ipfs/QmW4SgG4pDDLyFLy7V12QxMSx5X7tAqyeA4kgEFR1oURba/circuit.vkey.json](https://ipfs.io/ipfs/QmW4SgG4pDDLyFLy7V12QxMSx5X7tAqyeA4kgEFR1oURba/circuit.vkey.json) |
| witness\_wasm\_uri | [https://ipfs.io/ipfs/QmW4SgG4pDDLyFLy7V12QxMSx5X7tAqyeA4kgEFR1oURba/circom.wasm](https://ipfs.io/ipfs/QmW4SgG4pDDLyFLy7V12QxMSx5X7tAqyeA4kgEFR1oURba/circom.wasm) |
| zkey\_uri | [https://ipfs.io/ipfs/QmW4SgG4pDDLyFLy7V12QxMSx5X7tAqyeA4kgEFR1oURba/circuit\_final.zkey](https://ipfs.io/ipfs/QmW4SgG4pDDLyFLy7V12QxMSx5X7tAqyeA4kgEFR1oURba/circuit_final.zkey) |
Alternatively, you can find artifacts in our [github repo](https://github.com/Galxe/identity-protocol/tree/main/artifacts).
# Technical Components
Source: https://docs.galxe.com/identity/specification/technical-components
This section describes all the components implemented by the protocol.
### Verification stack: BabyZK
The initial zero-knowledge verification stack we have integrated is named "BabyZK". This stack employs the subsequent algorithms and parameters:
* **Curve**: BN254. All the following algorithms are using this curve.
* **Hash**: Poseidon.
* **Digest:** The digest is derived from the Poseidon hash of `poseidon(header, signature metadata)` and `poseidon(body)`. Initially, the header and signature metadata are cohesively hashed, according to the canonical sequence of header fields followed by signature metadata fields. Subsequently, the fields within the body are hashed in the type definition order. Finally we take the Poseidon hash of the two hash values.
* **Signature**: EdDSA Poseidon
* **Identity commitment schema:** a 2-input poseidon hash of BN254 curve of two fields: `identity secret` and `internal nullifier` , in this specified order.
* **Circuit language**: Circom
* **Proof system**: Groth16, powered by SnarkJS
* **Limits**: The total number of public inputs of claims in the body must be less than 256, including intrinsic public inputs. For body types encompassing more than 16 signals—such as 9 `uint256` fields or 20 `bool`—the fields are segmented into groups of 16 and individually hashed. The final step is hashing results from these group hashes. This approach is necessitated by Poseidon's constraint of 16 signals. Given the further restriction that there can't exceed 256 fields, this hashing methodology can be implemented through a two-layer hashing structure.
### Smart contracts
Smart contracts in the protocol serve two primary functions:
* **On-chain data storage:**
* Context registry
* Issuer registry
* Metadata
* Public key management
* Revocable credential state management
* Type registry
* Primitive type management
* Metadata
* Definition
* Resource URI
* Static proof verifier
* Public input parser
* Trust schema
* **On-chain Verification**:
* Stateful credential zk verifier contract
* Aggregated on-chain attestation
The Galxe identity protocol is crafted to be chain-agnostic, with plans to deploy these smart contracts across various EVM-compatible chains, including Ethereum, BSC, Polygon, and several Layer 2 solutions.
**Context registry**
A context is a string that, when paired with a credential type, forms a credential schema. This contract facilitates issuers in registering contexts, ensuring the meanings of credentials are publicly accessible.
* Issuers can introduce a new context by submitting a string to the contract. The Context ID is derived from the keccak256 hash of this string, truncated to the lower 160 bits.
* Contexts are designed to be universal, instead of binding to a credential type. While it might seem unconventional to associate a boolean-typed credential with the context "Trading volume," we entrust this decision to the issuer.
**Issuer registry**
This contract empowers issuers to register and authenticate their identities on-chain and manage the status of public keys and state of revocable credentials.
* **Issuer Metadata**:
* **Issuer ID**: Crafted to be chain-agnostic and deterministic, the issuer's EVM address is directly adopted as their Issuer ID. For chains not based on EVM, addresses can still be utilized, albeit truncated to 160 bits.
* **Name:** Issuer can specify their name.
* **Identity Verification** (built in separate contracts):
* **DNSSEC**: Issuers can use DNSSEC records to validate their ownership of web2 domains.
* **GAL Staking**: Issuers can manifest their commitment by staking GAL tokens.
* **ENS/SpaceID & Other Bindings**: This facilitates the association of issuers with a web3 identity.
* **Issuer State**:
* **Public Key Manager**: This contract caters to various verification stacks and is structured as a mapping from **`(issuer_id, key_id)`** to the key's status. The key ID is derived from the hash of the public key, with the hashing algorithm contingent on the selected verification stack. Key statuses are bifurcated into:
* **Active**: Denotes keys currently in use.
* **Revoked**: Signifies that all credentials signed with these keys are invalidated.
* **Signature State Manager**: For credentials that can be revoked, this contract provision allows issuers to regulate the revocation status for each combination of credential type and context. This is achieved by uploading the hash root of the sparse merkle tree containing signature IDs of the revoked credentials. Issuers need to publish the whole tree to a permanent storage for holders to access.
* URI to the sparse merkle tree.
* Root hash.
**Credential Type Registry**
The credential type registry contract serves as a comprehensive registry for managing credential types. Credential type designers can utilize this contract to introduce new types into the ecosystem, by storing all necessary artifacts on-chain. Issuers, holders, and verifiers will use this contract for creating new credentials, proof generation and verification.
* Type Registration
* Allows for the registration of new credential types by users.
* Type metadata storage
* Stores type metadata such as revocability, admin address, name, definition in DSL, description, and a resource URI for proof generation artifacts.
* Type Management
* Functionality to update the verifier and public signal getter for a type and a verification stack, adapting to evolving verification needs.
* Functionality to transfer type ownership.
* Check if a type is fully initialized for a given verification stack, ensuring readiness before deployment.
* Utility Functions
* Check if a type is fully initialized for a given verification stack, ensuring readiness before deployment.
* Calculate the typeID based on the creator's address and the name of the type
**Stateful verifier**
Besides using the verifier contract, that is associated with the credential type, to verify the validity of zero-knowledge proof, a full verification requires additional on-chain state validations, including:
1. Do type and context matches verifier’s expectation?
2. Can the revealed credential expiration lower bound prove that the credential is not expired? (greater or equal to the current blocktime)
3. Is the public key still active for the expected issuer?
4. If the credential is revocable, is the proof generated with the current SMT root?
For Babyzk, we built a contract that does all the checks in a simple function call `verifyProofFull`, so that verifiers can validate a proof with just one function call. It supports both:
* Static Verification: Checks the validity of proofs without considering the state of the issuer's public key or revocation lists.
* Full Verification: Extends static verification by also checking the issuer's public key activity and whether the revocation tree check is up-to-date.
**Trust Schema Manager**
This smart contract empowers verifiers to establish trust schemas tailored to specific verification scenarios. A straightforward example might involve enumerating a list of approved credential issuers. More intricate configurations could involve placing trust in issuers with active GAL staking, those operating under delegated trust, or issuers with a valid DNSSEC verification tied to some web2 domains. This contract transforms the trust establishment process into a communal activity, allowing trust schemas to be shared, voted upon, and dynamically adjusted.
Verifiers have the capability to introduce a new trust schema by supplying the address of a callback function. This function must be designated as a view function. The trust schema ID is then derived using a combination of the verifier's address and a nonce.
### SDK
The protocol provides an open source implementation of SDKs that allows developers to build application on Galxe identity protocol. The SDK provides:
1. Credential maker function: generate a credential based on its type.
2. BabyZK verification stack
1. circuit generator: generate circom code based on type definition.
2. signer: Sign a credential with private key.
3. proof generator: Generate a proof based on the type and conditions.
4. proof verifier: Based on the credential type, query verification key from blockchain and return the verification result. Users should always use the SDK’s proof verifiers or on-chain verifiers, when possible to enable type-based security checks.
### Hosted service
**Galxe BabyZK trust setup MPC node**
This is a hosted service that can participate in phase 2 trust setups for BabyZK’s Groth16 circuits. The service is not a necessity for protocol, but it can improve the user experience of credential type designer and its users. They do not need to worry about the trust setup when a new type is newly invented. The Galxe’s MPC node will make sure to add secrets into the result, seal and publish the proving and verification keys to decentralized storage and corresponding verifier.
### Application: Galxe identity vault
At the core of Galxe identity protocol’s philosophy lies a deep commitment to the idea of self-sovereign identity. In pursuit of ultimate sovereignty, we developed the **Galxe identity vault**, a local storage solution for identity data, with embedded zero-knowledge provers, that gives users
1. **self-evident privacy safeguard**: given that data is stored locally, users can ensure that their personal information is kept private. Data does not need to pass through or be stored on any external servers where it could potentially be accessed by unauthorized parties.
2. **total access control**: Local storage gives users full control over their own data. They can decide what to do with it, when to share it, how to share it, and who to share it with. This is in contrast to storing data with centralized authorities or intermediaries, where users must trust those authorities will handle their data appropriately, and hope their services are live when needed. With local storage, users can ensure that their data is stored in their own jurisdiction, avoiding potential legal and regulatory complications.
3. **no-code ZKP**: It allows credential type designer, issuer, verifier, and holder to run all the workflow without any coding.
The Galxe identity vault will be developed as an open-source reference implementation, and any party can build their own vaults as long as it follows the specification. The reference implementation of Galxe identity vault will be available as browser extensions and native Apps. Once installed, the user can start to collect verifiable credentials to build his self-sovereign identity.
By using zero-knowledge proof technologies, users will be able to practice data minimization, down to the least required. In practice, all computation on the credentials will happen on user’s local device via embedded zk-circuits, and only the public input and output will be shared with verifiers.
The wallet app must support:
* all the workflows defined below and
* generating a key pair on Baby Jubjub curve, which will be used for signing.
* sync and fetch credentials from issuers.
* checking on-chain state of revocable credentials.
* issuing credentials to any other identity
### Storage add-on(s)
The protocol can work with decentralized permanent storage to improve its user experiences, by storing these information:
1. Proving keys, which is required for holders to generate zero-knowledge proofs. The size of these keys range from one megabytes to even hundreds of megabytes, depending on the number of constraints of the circuit.
2. Sparse merkle tree of revoked credentials. Without the SMT data, holders cannot prove the validity of revocable credentials.
# Type DSL
Source: https://docs.galxe.com/identity/specification/type-dsl
Before we dive into the credential’s structure, it is crucial to introduce the concept of a credential type. To facilitate the use of ZK credentials without requiring deep dive into the underlying technology, we introduced a straightforward Domain-Specific Language (DSL). Credential type designers use this DSL to define credential types, outlining the expected claims, their respective types, and whether the credential can be revoked. A credential type is consist of a sequence of declarations of ***claims*** (also referred as ***fields*** in this paper). Like definition of struct in other programming languages, a declaration of claim has two components: an identifier and a type.
Additionally, whether a credential can be revoked by its issuer is also specified by its type. By default, credential is non-revocable and its validity can only be managed using the intrinsic expiration field. The DSL allows for the specification of revocability through the `@revocable(n)` pragma, where `n` denotes a positive integer indicating the depth of the sparse merkle tree used for managing revoked signatures. An SMT of depth `n` can accommodate `2^n` signatures. Developers should determine an optimal value by estimating the maximum number of credentials an issuer might distribute for a given context or type. The range for the depth spans from a minimum of 2 to a maximum of 248.
A semi-formal definition in BFN is as following:
```bnf theme={null}
::= ";" |
::= | ";"
::= ":"
::= |
::= "[" "]"
::= "bool" | "uint" "<" ">"
"prop" "<" "," "," ">"
::= "p" | "k" | "c"
::= "@" "(" ")"
::= number | string
::= /[a-zA-Z_][a-zA-Z0-9_]/
```
```
@revocable(16);
user_id:prop<128,p,2>;
age:uint<8>;
email_verified:bool;
owned_nft_ids:prop<32,p,1>[10];
```
In the current version, we support 3 types of claims:
1. **Bool**: Representing a boolean value, during proof generation, credential owners can choose to reveal or hide its value. This is due to its inherent limitation of equality check operation, which, when executed, inevitably discloses the value. For each bool-typed field, there will be one corresponding public signal in the proof, where `0` means the value is hidden, and `1` means the value is false, and `2` means the value is true.
2. **Property (string)**: Referred as "property type" in this document, this type is primarily designed for representing innumerable properties, such as "name". However, issuers can apply this value to enumerations as well. Issuers can use this type to store a string value. Internally, the string value will be converted to a hash value. There are three type parameters:
1. The `width` represents the width of the hash value. It must be byte-aligned and up to 248-bit;
2. The `hash_algorithm` designates which hash is used to transform the string into a hash value. If the hash value exceeds the specified `width`, only the `width` least significant bits will be used. The accepted values are `p | k | c`, where `p` stands for poseidon hash, `k` for keccak256, and `c` for a user-defined hash algorithm.
3. The optional parameter `num_equals_to_checks` , default to 1, specifies the number of values to be compared for one proof. There will be `num_equals_to_checks` output signals, where their least significant bit represents the equality, and the `[width+1…1]` bits convey the value that underwent comparison.
3. **Scalars**: Representing unsigned integers with bit-lengths spanning from 8 to 256, scalars are equipped to support range checks.
4. **Fixed-length array**: This type encapsulates arrays of the previously mentioned types. Operations specific to the underlying type can be executed on either an individual element or the entire array, facilitated by the **`one_of`** and **`all_of`** operators. Note that the **`any_of`** operator is redundant, as during the proofing phase, the holder is aware of which element is the desired value.
The following table summarizes a brief overview of the supported claim types, their syntax, and the operations applicable during proof generation.
| Claim type | Description | Supported operations | Public inputs |
| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bool` | A boolean value | reveal, hide | 0 means the value is hidden, and 1 means the value is false, and 2 means the value is true. |
| `prop` | A string representing some property of the holder, designed for innumerable properties. The big-length of property and the hash algorithm that maps the string to an unsigned integer which fits the width must be provided. | ==, ≠ | N output signals, where N equals to num\_equals\_to\_checks. Their least significant bit represents the equality, and the \[width+1…1] bits convey the value that underwent comparison. |
| `uint` | Scalar values, with width to be 8, 16, 32 … 256. | ≤, ≥ | 2 public inputs: lower\_bound and upper\_bound.
Note: for verification stack that does not support 256-bit numbers, e.g. babyzk, each number will be mapped to two signals, the lower 128 and the higher 128 bits. |
| `T[N]` | An fixed-length array of other values. | 1. oneOf(A, I, OP rhs).
2. allOf(A, OP rhs) | One public signal indicating if check was oneOf or allOf: 1 for oneOf, 2 for allOf, and one or two other signals are depending on the element type T. |
While the protocol does not impose a restriction on the number of fields in the body part, the verification stack might set a limit due to its inherent constraints of circuit size. For example babyzk stack limits the number of claims by setting the limit of public inputs to 256, including intrinsic signals.
# Workflow
Source: https://docs.galxe.com/identity/specification/workflow
Most workflows are depending the chosen verification stack. For demonstration, we will explain them of BabyZK.
### Type designer: create and publish a new credential type
Adding a new type to the protocol is a permission-less process. Type designer can use Galxe identity protocol SDK, or he can use Galxe identity vault for the no-code solution.
To introduce an official type, which will have long-term support of verification stacks, Galxe identity protocol employs a governance framework to facilitate decision-making regarding the acceptance and inclusion of new official credential types proposed by credential designers. The community, comprising users, developers, and other stakeholders, actively participates in the evaluation and acceptance process. Through transparent discussions and GAL voting mechanisms, the community collectively determines which proposed credential types are incorporated into the protocol.
The common workflow is:
1. Idea and Proposal: An individual or a group comes up with a new credential type. They draft a proposal document explaining the concept, its benefits, and technical specifications, including name and type of the fields, supported verification stack, zero-knowledge proof circuits, and details of the trust setup ceremony if required.
2. Community Feedback: The proposal is shared with the community for review and feedback. This can be done through forums, mailing lists, social media, or dedicated development channels like the official Galxe identity protocol github repository.
3. (Primitive) Type Number Assignment: If the proposal gains support and consensus within the community, an type number is assigned to it. The community uses these numbers to refer to specific proposals. Only applies to primitive types.
4. Audit and Security: Depending on the complexity and potential impact, an external security audit might be conducted to identify vulnerabilities or weaknesses in the proposal: (1) whether the wire format might be ambiguous, (2) if circuits were under-constrained or over-constrained, and (3) security level of the trust setup ceremony.
5. Voting and Adoption: Once the implementation passes security audits and testing and passes GAL voting process, it can be deployed to the Galxe identity protocol as a new official type.
| | Role (who’s doing it) | What | Input | Output | Modules |
| ---------------------------------------------------------------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1. Create credential type | Credential designer | Design a new credential type expressed in our DSL. | Credential type specification in DSL | ZK circuit | SDK, circuit generator |
| 2. Phase2 trusted setup for the type and circuit. Depending on the verification stack, this may be skipped | Credential designer + other parties (Galxe) | Phase2 setup for zk-related, specifically for babyzk stack’s proof system: Groth16 | ZK circuit | 1. proving key
2. verification key | The type designer needs to host a trusted setup ceremony for the circuit. Galxe identity protocol will provide an optional MPC node for participating the ceremony. |
| 3. Publish credential type | Credential designer | Type specification will be published on-chain, and a deterministic Type ID will be generated. For babyzk, verification key parameters must be updated to the verifier contract. | 1. proving key
2. verification key
3. Circuit artifacts like witness calculation WASM.
4. onchain verifier contract. | 1. Type ID.
2. add the verification key to the verifier.
3. proving key will be stored on decentralized storage. | contract:
1. Credential type registry.
2. Type-specific verifier contract.
Storage:
1. decentralized permanent storage. |
```
.--------..------------------..-------------. .----------------------------.
|Designer|| Protocol SDK ||Trusted setup| |(optional: Galxe-hosted MPC)|
'--------''------------------''-------------' '----------------------------'
| | | |
| Type DSL | | |
|------------->| | |
| | | |
|circom circuit| | |
|<-------------| | |
| | | |
| circom circuit | |
|------------------------------->| |
| | | |
| | | *.zkey |
| | |--------------------------->|
| | | |
| | |proving and verification key|
| | |<---------------------------|
| | | |
| proving and verification key | |
|<-------------------------------| |
```
```
.--------. .-------..-----. .-------------.
|Designer| |Storage||Chain| |Type Registry|
'--------' '-------''-----' '-------------'
| | | |
|Circuit artifacts| | |
|---------------->| | |
| | | |
| Resource URI | | |
|<----------------| | |
| | | |
|Deploy verifier contract | |
|------------------------>| |
| | | |
|Type specification, resource URI, verifier|
|----------------------------------------->|
```
### Issuer: register and issue credentials
| | Role (who’s doing it) | What | Input | Output | Modules |
| ------------------------------------ | --------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------- |
| 4. Register as an issuer | Issuer | Register to become an issuer. | 1. metadata
2. public keys
3. proof of identities. | issuer ID | Issuer registry + pubkey manager for different verification stack |
| 5. Register a new credential context | Issuer | Add a new context on-chain. | 1. CredType ID.
2. Context string | context ID | contract: context registry
Context ID: hash of context string cut to 160 bits, from LSB. |
| 6. Issue a new credential | Issuer ←→ owner | Sign a new credential to user. | 1. credential header
2. claim values.
3. user’s identity commitment
4. signature | a credential in JSON | SDK |
To become an issuer, one can register on-chain. The issuer ID is computed deterministically based on the caller’s address. Issuers can add proofs of identity to show his accountability, e.g., DNSSEC verification, and GAL staking. It is recommended to use a smart contract wallet, e.g. ERC-4337 wallet, to register the issuer, for permission management.
```
.------. .---------------..-----------------.
|issuer| |Issuer Registry||Identity contract|
'------' '---------------''-----------------'
| | |
| metadata | |
|----------------------->| |
| | |
| proof of identity |
|----------------------------------------->|
| | |
|active/remove public key| |
|----------------------->| |
```
Before issuing a credential, issuer must decide the credential schema, which is the type and context of credential. The context is a string that describes the content of the credential. For example, for a credential that proves a user’s total USD value of financial assets, issuer can use the basic credential type ‘scalar’, and its context can be a string of “total USD value of financial assets”. The separation of context and type in a the credential schema allows users to reuse the pre-compiled zero-knowledge proof circuits. Note that credential schema is universal, meaning that you can use a schema that is created by some other issuers. This can also be useful during verification: a verifier can program the logic of which schema to accept, from a simple list of schema IDs to dynamic logic programmed on-chain.
```
.------. .----------------.
|Issuer| |Context Registry|
'------' '----------------'
| |
|Type ID and context string|
|------------------------->|
| |
| context ID |
|<-------------------------|
```
One important benefit of Galxe identity protocol is that, credential issuance can happen completely off-chain. The issuing process requires holder to provide an identity commitment to the issuer. An issuer must maintain a strict 1-to-1 mapping from the unique ID of the under the application to the identity commitment. In another word, a user must use the same commitment for an issuer. If the issuer failed to do so, the holder can create multiple proofs of different nullifiers, which allow him to ‘double-spend’ the credential.
Note that this interactive process can be improved by using [PLUME](https://eprint.iacr.org/2022/1255.pdf), if the ID is a public key. However, due to the high cost (over 2M constraints) under BabyZK stack, it is currently not supported.
```
.------. .------. .---------------------.
|Holder| |Issuer| |Identity Protocol SDK|
'------' '------' '---------------------'
| | |
|identity commitment| |
|------------------>| |
| | |
| |credential header, claims, signing key|
| |------------------------------------->|
| | |
| | verifiable credential |
| |<-------------------------------------|
| | |
| credential | |
|<------------------| |
```
After issuing credentials, issuers can still manage their validity on-chain, if they are revocable. the protocol provides different ways to do it
1. Signing key management. Signing keys can be marked as active or deprecated. Verifiers should never trust any credential that is signed by a deprecated key.
2. Expiration date embedded in the signature.
3. Revocable credentials: sparse merkle tree (SMT) of signature IDs.
| | Role (who’s doing it) | What | Input | Outcome | Modules |
| ------------------------- | --------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | --------------- |
| 6.1 Credential revocation | issuer | Issuers can manage the ‘signatures’ they signed on credentials. | 1. expiration.
2. signature ID via SMT.
3. explicitly seal the credential. | Credential will be revoked, holder cannot generate proofs that satisfy the goal. | Issuer Registry |
### Owner: proof generation and identity management
| | Role (who’s doing it) | What | Input | Outcome | Modules |
| ---------------------- | --------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------ | ---------------------------------------------------------------------------- |
| 7. zk-proof generation | owner | Credential holder can generate a proof against a set of conditions. | 1. credential.
2. conditions.
3. proving key.
4. external nullifier | 1. proof
2. public data | Galxe identity vault or any apps that have integrated identity protocol SDk. |
Owners can generate proofs that they hold a credential satisfying some constraints. This is done by using the circuit generated from compiled for the credential type. Using the credential and the conditions that will be checked as input, user can generate a succinct proof showing that the holder has a credential satisfying conditions.
```
.-------. .-----. .------------.
|Storage| |Owner| |Protocol SDK|
'-------' '-----' '------------'
| | |
|Proof gen artifacts| |
|------------------>| |
| | |
| |identity secrets, pseudonym, credential, and statements|
| |------------------------------------------------------>|
| | |
| | proof and public input |
| |<------------------------------------------------------|
.-------. .-----. .------------.
|Storage| |Owner| |Protocol SDK|
'-------' '-----' '------------'
```
### Verifier: verify proofs
Verifiers can validate a proof both on-chain and off-chain. Their respective workflows are shown as below:
| | Role (who’s doing it) | What | Input | Outcome | Modules |
| ----------------------------------- | --------------------- | ------------------------------------------------------------------------------ | ----------------------------------- | ------------- | ------------------------------------------------- |
| 9. zk-based credential verification | verifier | Owners can submit a proof to verifier that some statements about them is true. | 1. proof.json
2. public.json | accept/reject | Stateful verifier, type registry, issuer registry |
On-chain verification is extremely simple. Verifiers just need to submit the proof and the public input to the stateful verifier. For most of the cases, we recommend applications to use on-chain verification even for off-chain verification, by making an external call to the stateful verifier contract via RPC.
```json theme={null}
.--------. .-----------------.
|Verifier| |Stateful verifier|
'--------' '-----------------'
| |
|proof and public inputs|
|---------------------->|
| |
| verification result |
|<----------------------|
```
Off-chain verification also rely on some on-chain states, for example, verification key and public key status. However, note that these values can be cached in some use cases, for example, when applications are sure that some public keys are always valid. In those cases, after initial setup, verifiers do not need to query anything on-chain.
```
.--------. .--------------..-----------------..---------------..------------.
|Verifier| |Typed registry||Verifier contract||Issuer registry||Protocol SDK|
'--------' '--------------''-----------------''---------------''------------'
| | | | |
|verifier contract address| | | |
|<------------------------| | | |
| | | | |
| verification key | | |
|<------------------------------------------| | |
| | | | |
| public key status, revocation SMT root | |
|<------------------------------------------------------------| |
| | | | |
| vkey, key status, SMT root, proof and public inputs |
|--------------------------------------------------------------------------->|
| | | | |
| | verification result | |
|<---------------------------------------------------------------------------|
```
# Proof Generation & Verification Workflow
Source: https://docs.galxe.com/identity/tutorials/simple-workflow
Hands-On Zero-Knowledge Proofs with Galxe Identity Protocol
## Introduction
This tutorial guides you through the process of issuing and verifying credentials using Galxe Identity Protocol on Ethereum. You will learn how to create and sign a credential, generate a zero-knowledge proof, and perform both on-chain and off-chain verifications.
## Prerequisites
* Basic understanding of Ethereum and smart contracts.
* Node.js installed on your machine.
* An IDE or text editor for writing JavaScript code.
## Step 1: Setup and initialize Nodejs repo
In your Node.js repo, run:
```bash theme={null}
npm install @galxe-identity-protocol/sdk ethers
```
## Step 2: Import necessary dependencies and setup issuer
Do not use the dummy issuer in production.
Note that the dummy issuer has been registered on Ethereum mainnet. Check out the registration transaction [here](https://etherscan.io/tx/0xfbf58513352fe0dc899544b66013adbacb90437210e0008ceeb7b9c9ecec5bdd).
This issuer is registered with the following parameters:
| parameter | type | input |
| ------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| name | string | demo-issuer (don't trust me) |
| verificationStackId | uint8 | 1 |
| publicKeyId | uint256 | 1743582416365651167392966598529843347617363862106697818328310770809664607117 |
| publicKeyRaw | bytes | 0x1adaddae1888a2b6e91240896f5e50379520137f76c424755217ade00f8b2d185a05a904d745ee24692d91cf74425d4271817e64e630115469f3f289d0d06b2f |
* `verificationStackId = 1` means that this issuer is registered for babyzk stack
```typescript theme={null}
import {
prepare,
credential,
evm,
credType,
errors,
user,
issuer,
babyzk,
utils,
statement,
claimType,
babyzkTypes,
} from "@galxe-identity-protocol/sdk";
import { ethers } from "ethers";
// conviniently unwrap the result of a function call by throwing an error if the result is an error.
const unwrap = errors.unwrap;
// Use cloudflare's free open rpc in this example.
const MAINNET_RPC = "https://cloudflare-eth.com";
const provider = new ethers.JsonRpcProvider(MAINNET_RPC);
// This is a dummy issuer's EVM address that has been registered on mainnet.
// Because it authroize the private key that is public to everyone,
// it should not be used in production!
const dummyIssuerEvmAddr = "0x15f4a32c40152a0f48E61B7aed455702D1Ea725e";
```
## Step 3: Issue a new credential
Note that this context has been registered on Ethereum mainnet. Check out the registration transaction [here](https://etherscan.io/tx/0xfec5eea6c7781db45265038a64023ee74d002e240978a6483a3291177b9c63e8).
```typescript theme={null}
async function issuingProcess(userEvmAddr: string, userIdc: bigint) {
// 1. First of all, we must create the type of the credential.
// In this example, Let's use the primitive type Scalar.
const typeSpec = credType.primitiveTypes.scalar;
const tp = unwrap(credType.createTypeFromSpec(typeSpec));
// 2. Creating a credential based on the type.
// In general, this is when the issuer decides "claims" about the user.
// Because we are issuing a credential that represents the number of transactions,
// let's fetch it from the Ethereum network.
const txCount = await provider.getTransactionCount(userEvmAddr);
// The contextID is a unique identifier representing the context of the credential.
// We will just use the string "Number of transactions".
// NOTE: The contextID must be registered on the chain before issuing the credential for visibility.
const contextID = credential.computeContextID("Number of transactions");
// Now, let's create the credential.
const newCred = unwrap(
credential.Credential.create(
{
type: tp,
contextID: contextID,
userID: BigInt(userEvmAddr),
},
{
val: BigInt(txCount).toString(), // credential value, number of transactions
}
)
);
// Add additional attributes to the credential attachments, if needed
// these attributes will not be part of the zero-knowledge proof, but
// they will be signed by the issuer as well.
// So, you must add them before signing the credential.
newCred.attachments["creativity"] = "uncountable";
// 3. Signing the credential.
// After the credential is created, it must be signed by the issuer.
// The issuer must have been registered on the chain, at least on the chain of the supplied ChainID.
// Registering the issuer on more chains is recommended for better interoperability.
// Also, the signing key's keyID must be active correspondingly on chains.
// For demonstration purposes, we use the dummy issuer with a publicly known key.
// The dummy issuer has been registered on etheruem mainnet, and the following key is also activated.
// Don't use this issuer or key in production!
const issuerID = BigInt(dummyIssuerEvmAddr);
const issuerChainID = BigInt(1); // mainnet
// A mock private key for the signer, which is used to sign the credential.
// This key has been registered and activated on mainnet by the dummy issuer.
const dummyKey = utils.decodeFromHex(
"0xfd60ceb442aca7f74d2e56c1f0e93507798e8a6e02c4cd1a5585a36167fa7b03"
);
const issuerPk = dummyKey;
// create a new issuer object using the private key, issuerID, and issuerChainID.
const myIssuer = new issuer.BabyzkIssuer(issuerPk, issuerID, issuerChainID);
// sign the credential to user's identity commitment, with a unique signature id and expiration date.
myIssuer.sign(newCred, {
sigID: BigInt(100),
expiredAt: BigInt(
Math.ceil(new Date().getTime() / 1000) + 7 * 24 * 60 * 60
), // assuming the credential will be expired after 7 days
identityCommitment: userIdc,
});
// all done, return the credential to the owner.
return newCred;
}
```
## Step 4: Proof generation
```typescript theme={null}
async function proofGenProcess(myCred: credential.Credential, u: user.User) {
// Now issuer can issue a credential to the user.
// In this example, we will issue a credential that represents the number of transactions,
// that the user has made on the Ethereum, at the time of issuance.
// Assuming that the user has received the credential,
// user can generate a zk proof to prove that he has sent more than 500 transactions, but no more than 5000.
// Let's first decide the external nullifier for the proof.
const externalNullifier = utils.computeExternalNullifier(
"Galxe Identity Protocol tutorial's verification"
);
// Now we need to fetch the proof generation gadgets. It is explicitly fetched outside the proof generation function
// because usually, the proof generation gadgets are stored in a remote server, and may be large (3-10MB).
// It's highly recommended to cache the proof generation gadgets locally.
console.log("downloading proof generation gadgets...");
const proofGenGagets = await user.User.fetchProofGenGadgetsByTypeID(
myCred.header.type,
provider
);
console.log("proof generation gadgets are downloaded successfully.");
// Finally, let's generate the proof.
const proof = await u.genBabyzkProof(
u.getIdentityCommitment("evm")!,
myCred,
// proof generation options
{
expiratedAtLowerBound: BigInt(
Math.ceil(new Date().getTime() / 1000) + 3 * 24 * 60 * 60
), // assume that we want to verify that the credential is still valid after 3 days.
externalNullifier: externalNullifier,
equalCheckId: BigInt(0), // do not reveal the credential's actual id, which is the evm address in this example
// Instead, claim to be Mr.Deadbeef. It's verifier's responsibility to verify that
// the pseudonym is who he claims to be, after verifying the proof.
pseudonym: BigInt("0xdeadbeef"),
},
proofGenGagets,
// statements to be proved, in this case, we want to prove that the credential's first uint248 value is between 500 and 5000, inclusively.
[new statement.ScalarStatement(new claimType.ScalarType(248), 500n, 5000n)]
);
return proof;
}
```
## Step 5: Proof verification
Proof verification can be made both on-chain and off-chain. Here we demonstrates both options:
### On-chain verification
```typescript theme={null}
async function verifyByCallingEvmStatefulVerifier(
proof: babyzkTypes.WholeProof
): Promise {
// As a verifier, we must decide the expected
// contextID, issuerID, and typeID of the credential.
const expectedContextID = credential.computeContextID(
"Number of transactions"
);
const expectedIssuerID = BigInt(dummyIssuerEvmAddr);
const expectedTypeID = credType.primitiveTypes.scalar.type_id;
// A proof can be verified both on-chain or off-chain.
// Let's take a look at the on-chain verification first.
// It is just 1 simple function call.
const statefulVerifier = evm.v1.createBabyzkStatefulVerifier({
signerOrProvider: provider,
});
const statefulVerifierResult = await statefulVerifier.verifyWholeProofFull(
expectedTypeID,
expectedContextID,
expectedIssuerID,
proof
);
if (statefulVerifierResult !== evm.VerifyResult.OK) {
console.error(
"Proof verification failed, reason: ",
evm.verifyResultToString(statefulVerifierResult)
);
} else {
console.log("On-chain stateful proof verification is successful.");
}
return true;
}
```
### Off-chain verification
```typescript theme={null}
async function verifyByOffchain(
proof: babyzkTypes.WholeProof
): Promise {
// As a verifier, we must decide the expected
// contextID, issuerID, and typeID of the credential.
const expectedContextID = credential.computeContextID(
"Number of transactions"
);
const expectedIssuerID = BigInt(dummyIssuerEvmAddr);
const expectedTypeID = credType.primitiveTypes.scalar.type_id;
// Alternatively, you can use the off-chain verification.
// When using off-chain verification, you must first get the verification key.
// You can embed the verification key in your application, or fetch it from a remote server.
// We will fetch the verification key from the chain in this example.
// The first step is to do a static proof verification, making sure that the zk proof is valid.
const tpRegistry = evm.v1.createTypeRegistry({
signerOrProvider: provider,
});
const verifier = await tpRegistry.getVerifier(
expectedTypeID,
credential.VerificationStackEnum.BabyZK
);
const vKey = await verifier.getVerificationKeysRaw();
// off-chain proof verification
const verifyResult = await babyzk.verifyProofRaw(vKey, proof);
console.log("off-chain static proof verification result: ", verifyResult);
// NOTE: you can also do the static proof verification part on-chain
// See the commented code below.
// const onChainVerifyResult = await verifier.verifyWholeProof(proof);
// console.log(
// "on-chain static proof verification result: ",
// onChainVerifyResult
// );
// After the static proof verification is successful, you will need to do
// some addition on-chain stateful checks and off-chain checks.
// Check If the public key is active.
const IssuerRegistry = evm.v1.createIssuerRegistry({
signerOrProvider: provider,
});
const pubkeyId = babyzk.defaultPublicSignalGetter(
credential.IntrinsicPublicSignal.KeyId,
proof
);
if (pubkeyId === undefined) {
return false;
}
// check on-chain if the public key is active by the issuer.
const isActive = await IssuerRegistry.isPublicKeyActiveForStack(
expectedIssuerID,
pubkeyId,
credential.VerificationStackEnum.BabyZK
);
if (!isActive) {
console.error("The public key is not active.");
return false;
}
// some off-chain checks
const contextId = babyzk.defaultPublicSignalGetter(
credential.IntrinsicPublicSignal.Context,
proof
);
if (contextId === undefined) {
console.error("Context ID is not found in the proof.");
return false;
}
if (contextId !== expectedContextID) {
console.error(
`Context ID is not as expected: ${contextId}, expected: ${expectedContextID}`,
`${typeof contextId}, ${typeof expectedContextID}`
);
return false;
}
const expiredAtLb = babyzk.defaultPublicSignalGetter(
credential.IntrinsicPublicSignal.ExpirationLb,
proof
);
if (expiredAtLb === undefined) {
console.error("Expiration time is not found in the proof.");
return false;
}
if (expiredAtLb < BigInt(Math.ceil(new Date().getTime() / 1000))) {
console.error("The credential is expired.");
return false;
}
// NOTE: you will need to check if the credential is revoked or not, if the credential type supports revocation.
// We will not cover the revocation in this example, because we used a primitive type that does not support revocation.
console.log("Off-chain verification is successful.");
return true;
}
```
## Step 6: Put it all together
```typescript theme={null}
async function main() {
// prepare must be called by the application before any other function.
await prepare();
// The very first step is to create a user with a random identity.
// This should be done on user's device and the identity should be stored securely.
const u = new user.User();
const evmIdSlice = u.createNewIdentitySlice("evm");
// User's identity commitment is computed based on the secrets of the identity slice.
// You can also retrive the identity commitment from the identity slice.
const userIdc = user.User.computeIdentityCommitment(evmIdSlice);
// let's use a famous Ethereum address in this example.
const userEvmAddr = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
// Issuer's process: issuing a credential to the user.
const myCred = await issuingProcess(userEvmAddr, userIdc);
console.log("Credential is issued successfully.");
console.log(myCred.marshal(2));
// User's process: generating a zk proof to prove some statements about the credential.
const proof = await proofGenProcess(myCred, u);
console.log("Proof is generated successfully.", proof);
// Verification process: verifying the proof.
await verifyByCallingEvmStatefulVerifier(proof);
// Alternatively, you can verify the proof off-chain.
await verifyByOffchain(proof);
process.exit(0);
}
main();
```
## Example output
```
Credential is issued successfully.
{
"header": {
"version": "1",
"type": "3",
"context": "76531616260669148123754708449894501309630588037",
"id": "1238012972454248237435767387143779415173800484933"
},
"body": {
"val": "1230"
},
"signatures": [
{
"metadata": {
"verification_stack": 1,
"signature_id": "100",
"expired_at": "1713809756",
"identity_commitment": "607258966955358541979569552241800390247193769644933770458665842211944003189",
"issuer_id": "125344402375953606533377270523694284815265854046",
"chain_id": "1",
"public_key": "GtrdrhiIorbpEkCJb15QN5UgE392xCR1Uhet4A+LLRhaBakE10XuJGktkc90Ql1CcYF+ZOYwEVRp8/KJ0NBrLw=="
},
"signature": "JoCOG4g8Zh6HbRx6CiB8iT+IFRv7rODqkKOun/ZRPK+AXczTT/naAKDFPLmeSi9vJNmyivXJOTI0rrFZqqtPBA==",
"attachmentsSignature": "5BJbz+KoS3fNM/nIEHZ8dJNnNoI7Sfj9dyVuITPqOxu+7WDqQPZi8hRYWnWHbKwu7WyzaX/FwibgS/PHpY0DBA=="
}
],
"attachments": {
"creativity": "uncountable"
}
}
downloading proof generation gadgets...
proof generation gadgets are downloaded successfully.
Proof is generated successfully. {
proof: {
pi_a: [
'14098169155626322701575686270030877135793179179958248476088718329427027211313',
'10166291938235695325174257585123622443224042363089146982965433209462199866261',
'1'
],
pi_b: [ [Array], [Array], [Array] ],
pi_c: [
'2232690526946879183375289587329787117413207137997669929492279533329962669798',
'2812892456912632652909338355747715034651129220189926137857946196375602442475',
'1'
],
protocol: 'groth16',
curve: 'bn128'
},
publicSignals: [
'3',
'76531616260669148123754708449894501309630588037',
'20262325705979633926857839541911120644083373009050920843747535916548539604767',
'3735928559',
'515399344354422600182581914538985155404062012635',
'1713464160',
'1743582416365651167392966598529843347617363862106697818328310770809664607117',
'0',
'500',
'5000'
]
}
On-chain stateful proof verification is successful.
off-chain static proof verification result: true
Off-chain verification is successful.
```
# Conclusion
Congratulations! You've successfully issued a credential, generated a zero-knowledge proof, and verified it both on-chain and off-chain. This tutorial demonstrates the powerful capabilities of the Galxe Identity Protocol in maintaining privacy and security through zero-knowledge proofs.
# Proof Aggregation & Verification with NEBRA
Source: https://docs.galxe.com/identity/tutorials/use-nebra-upa
Utilizing NEBRA as proof aggregator
## Introduction
Galxe Identity Protocol SDK is capable to utilize NEBRA's proof aggregation tech to drastically reduce the costly onchain proof verifications. To learn more on NEBRA, click [here](https://www.nebra.one).
This tutorial guides you through the process of using Nebra UPA to aggregate and verify credentials on Sepolia.
Note that:
1. Nebra is currently live only on Sepolia testnet.
2. This tutorial will run for a few minutes as it waits for the proof submission to be aggregated by Nebra and verified on-chain.
## Prerequisites
To run this tutorial, you need to have an funded address on Sepolia as Nebra signer. This address is used to submit proofs to the Nebra Upa receiver. Example proof submission transaction can be found [here](https://sepolia.etherscan.io/tx/0x6e09db9f92aa7bf110400e61f840a39ee420a7176e1da5e4bf5683c6e56ef574).
* Create `.env` file using `.env.example` as a template. Update `NEBRA_SIGNER_PK` with your private key.
## Step 1: Setup and initialize Nodejs repo
In your Node.js repo, run:
```bash theme={null}
npm install @galxe-identity-protocol/sdk ethers @nebrazkp/upa
```
## Step 2: Import necessary dependencies and setup issuer
Note that the dummy issuer used in this tutorial has been registered on Sepolia testnet. Check out the registration transaction [here](https://sepolia.etherscan.io/tx/0x89c0cf5af6f6c0b6750bd6b3a4b93c02605d0ba1541c26387ed7da3ae7df3ffa).
This issuer is registered with the following parameters:
| parameter | type | input |
| ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| name | string | demo-issuer (don't trust me) |
| verificationStackId | uint8 | 1 |
| publicKeyId | uint256 | 18776893102620642575656716525121755312642649464684953450234247405793284298744 |
| publicKeyRaw | bytes | 0x0435be315dd7c00c9ba151f7c811bde6598c2e1b1f30552a3fb07a34b6c91416a99883f708f3389842c8f43c1c272bb8210a68d25f09201887354d85e8e58beff0 |
* `verificationStackId = 1` means that this issuer is registered for babyzk stack
## Step 3: Register your circuit on NEBRA
Since this tutorial uses the `Unit` primitive type, you can skip this step and use the pre-registered circuit ID instead - `535783125321978663259414080602879573584328345995263811920911450103380255481`.
This circuit is registed with this [transaction](https://sepolia.etherscan.io/tx/0x89c0cf5af6f6c0b6750bd6b3a4b93c02605d0ba1541c26387ed7da3ae7df3ffa).
To register your own circuit, follow the tutorial [here](https://docs.nebra.one/developer-guide/registering-applications).
## Step 4: Let's dive in to the code
Code used in this tutorial is also available [here](https://github.com/Galxe/identity-protocol/blob/main/apps/tutorial/src/useNebraUpa.ts).
```typescript theme={null}
import "dotenv/config";
import {
prepare,
credential,
evm,
credType,
errors,
user,
issuer,
utils,
} from "@galxe-identity-protocol/sdk";
import { ethers } from "ethers";
import { UpaClient, CircuitIdProofAndInputs, Proof } from "@nebrazkp/upa/sdk";
import * as fs from "fs";
// conviniently unwrap the result of a function call by throwing an error if the result is an error.
const unwrap = errors.unwrap;
// Use Ankr's free open rpc in this example.
const RPC = "https://rpc.ankr.com/eth_sepolia";
const provider = new ethers.JsonRpcProvider(RPC);
const context = "Proof Aggregation Tutorial Example Context";
// registered with this tx:
// https://sepolia.etherscan.io/tx/0x89c0cf5af6f6c0b6750bd6b3a4b93c02605d0ba1541c26387ed7da3ae7df3ffa
const circuidId = BigInt(
"535783125321978663259414080602879573584328345995263811920911450103380255481"
);
// This is a dummy issuer's EVM address that has been registered on sepolia.
const dummyIssuerEvmAddr = "0xdeee54e0f3cbb7d5c4b2cb91d39c9c9b48a1b532";
// demonstration of the issuingProcess.
async function issuingProcess(userEvmAddr: string, userIdc: bigint) {
const typeSpec = credType.primitiveTypes.unit;
const tp = unwrap(credType.createTypeFromSpec(typeSpec));
const contextID = credential.computeContextID(context);
// Now, let's create the credential.
const newCred = unwrap(
credential.Credential.create(
{
type: tp,
contextID: contextID,
userID: BigInt(userEvmAddr),
},
{}
)
);
newCred.attachments["creativity"] = "uncountable";
// signing the credential.
const issuerID = BigInt(dummyIssuerEvmAddr);
const issuerChainID = BigInt(11155111); // sepolia
// A mock private key for the signer, which is used to sign the credential.
// This key has been registered and activated on sepolia by the dummy issuer.
// pub key: 0x0435be315dd7c00c9ba151f7c811bde6598c2e1b1f30552a3fb07a34b6c91416a99883f708f3389842c8f43c1c272bb8210a68d25f09201887354d85e8e58beff0
const dummyKey = utils.decodeFromHex(
"0x8d06429619a08325ea79a575e1df14787be5223614403a9142360616811f7aea"
);
const issuerPk = dummyKey;
// create a new issuer object using the private key, issuerID, and issuerChainID.
const myIssuer = new issuer.BabyzkIssuer(issuerPk, issuerID, issuerChainID);
// sign the credential to user's identity commitment, with a unique signature id and expiration date.
myIssuer.sign(newCred, {
sigID: BigInt(100),
expiredAt: BigInt(
Math.ceil(new Date().getTime() / 1000) + 7 * 24 * 60 * 60
), // assuming the credential will be expired after 7 days
identityCommitment: userIdc,
});
// all done, return the credential to the owner.
return newCred;
}
// demonstration of the proofGenProcess.
async function proofGenProcess(myCred: credential.Credential, u: user.User) {
const externalNullifier = utils.computeExternalNullifier(
"Galxe Identity Protocol tutorial's verification"
);
console.log("downloading proof generation gadgets...");
const proofGenGagets = await user.User.fetchProofGenGadgetsByTypeID(
myCred.header.type,
provider
);
console.log("proof generation gadgets are downloaded successfully.");
// Let's generate the proof.
// Assume that we want to verify that the credential is still valid after 3 days.
const expiredAtLowerBound = BigInt(
Math.ceil(new Date().getTime() / 1000) + 3 * 24 * 60 * 60
);
// Do not reveal the credential's actual id, which is the evm address in this example
const equalCheckId = BigInt(0);
// Instead, claim to be Mr.Deadbeef. It's verifier's responsibility to verify that the pseudonym is who
// he claims to be, after verifying the proof.
const pseudonym = BigInt("0xdeadbeef");
// Here we ignore the conditions and just use the options in the query, since unit credential needs no conditions.
const proof = await u.genBabyzkProofWithQuery(
u.getIdentityCommitment("evm")!,
myCred,
proofGenGagets,
`
{
"options": {
"expiredAtLowerBound": "${expiredAtLowerBound}",
"externalNullifier": "${externalNullifier}",
"equalCheckId": "${equalCheckId}",
"pseudonym": "${pseudonym}"
}
}
`
);
return proof;
}
async function verifyByCallingAggregatedStatefulVerifier(
publicSignals: string[]
): Promise {
// As a verifier, we must decide the expected
// contextID, issuerID, and typeID of the credential.
const expectedContextID = credential.computeContextID(context);
const expectedIssuerID = BigInt(dummyIssuerEvmAddr);
const expectedTypeID = credType.primitiveTypes.unit.type_id;
// Let's take a look at the on-chain verification first.
// It is just 1 simple function call.
const aggregatedStatefulVerifier =
evm.v1.createAggregatedBabyzkStatefulVerifier({
signerOrProvider: provider,
});
const statefulVerifierResult =
await aggregatedStatefulVerifier.verifyProofFull(
expectedTypeID,
expectedContextID,
expectedIssuerID,
circuidId,
publicSignals
);
if (statefulVerifierResult !== evm.VerifyResult.OK) {
console.error(
"Proof verification failed, reason: ",
evm.verifyResultToString(statefulVerifierResult)
);
} else {
console.log("On-chain stateful proof verification is successful.");
}
return true;
}
async function main() {
// prepare must be called by the application before any other function.
await prepare();
// setup UPA
const upaInstanceDescriptor = JSON.parse(
fs.readFileSync("upa.instance", "ascii")
);
// eslint-disable-next-line turbo/no-undeclared-env-vars
const signer = new ethers.Wallet(process.env.NEBRA_SIGNER_PK!, provider);
const upaClient = new UpaClient(signer, upaInstanceDescriptor);
// The very first step is to create a user with a random identity.
// This should be done on user's device and the identity should be stored securely.
const u = new user.User();
const evmIdSlice = u.createNewIdentitySlice("evm");
// User's identity commitment is computed based on the secrets of the identity slice.
// You can also retrive the identity commitment from the identity slice.
const userIdc = user.User.computeIdentityCommitment(evmIdSlice);
// let's use a famous Ethereum address in this example.
const userEvmAddr = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
// Issuer's process: issuing a credential to the user.
const myCred = await issuingProcess(userEvmAddr, userIdc);
console.log("Credential is issued successfully.");
console.log(myCred.marshal(2));
// User's process: generating a zk proof to prove some statements about the credential.
const proof = await proofGenProcess(myCred, u);
console.log("Proof is generated successfully.", proof);
const circuitIdProofAndInputs: CircuitIdProofAndInputs[] = [
{
circuitId: circuidId,
proof: Proof.from_snarkjs(proof.proof),
inputs: proof.publicSignals.map((x) => BigInt(x)),
},
];
const submissionHandle = await upaClient.submitProofs(
circuitIdProofAndInputs
);
const submitProofTxReceipt = await upaClient.waitForSubmissionVerified(
submissionHandle
);
console.log("Proof is submitted successfully.", submitProofTxReceipt);
// Now that our proof submission has been verified, we can just verify the
// proof using public signals only.
await verifyByCallingAggregatedStatefulVerifier(proof.publicSignals);
process.exit(0);
}
main();
```
While this looks similar to the previous tutorial, the main differences here is the proof verification process. Let's take a look at the main function. Instead of verifying the proof on-chain with our stateful verifier like in the previous tutorial, we submit the proof to Nebra UPA instead and once submission is verified, we verify the proof using the public signals only.
Proof is submitted to Nebra UPA using the `submitProofs` function. This function returns a submission handle which can be used to wait for the submission to be verified using the `waitForSubmissionVerified` function. `waitForSubmissionVerified` will run for a while since it takes time for the proof to be aggregated by NEBRA and verified on-chain.
```typescript theme={null}
const submissionHandle = upaClient.submitProofs(circuitIdProofAndInputs);
const submitProofTxReceipt = await upaClient.waitForSubmissionVerified(
submissionHandle
);
console.log("Proof is submitted successfully.", submitProofTxReceipt);
```
And note that in `verifyByCallingAggregatedStatefulVerifier`, we can now verify the proof using the public signals only with `aggregatedStatefulVerifier.verifyProofFull`.
# Conclusion
Congratulations! You've successfully issued a credential, generated a zero-knowledge proof, submit the proof to be aggregated by NEBRA, and verified it on-chain. This tutorial demonstrates how NEBRA can be utilized to aggregate and verify proofs off-chain, reducing the costly on-chain proof verifications.
The code used in this tutorial is available [here](https://github.com/Galxe/identity-protocol/blob/main/apps/tutorial/src/useNebraUpa.ts)
# Galxe Passport
Source: https://docs.galxe.com/identity/use-cases/galxe-passport
Issue and verify Galxe Passport v2 credential
You can claim your Galxe Passport here: [https://app.galxe.com/passport](https://app.galxe.com/passport)
## Passport v2.1
In mid-September 2024, we upgraded Passport from version v2.0 to v2.1. Key updates include:
* Added `document_expiration_date` to the schema, allowing rejection of documents that are near expiration.
* Introduced `proof_of_time` to the schema, which tracks the time difference between the first and most recent verification. For example, if a user first verified their government ID in 2022 and re-verified their selfie in 2024, the time delta is 2 years, increasing confidence in the user's authenticity.
* Added `last_revoke_time` to the schema to store the timestamp of the user's most recent passport revocation.
New users will automatically receive their passport credential in v2.1. Existing users on v1 and v2 can upgrade by clicking the upgrade button at [https://app.galxe.com/passport](https://app.galxe.com/passport).
### Type
"Galxe Passport v2.1" credential type is registered onchain as a custom primitive type with type ID 10001.
| Type ID | Name | Description | Definition | Example |
| ------- | ------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| 10001 | Galxe Passport v2.1 | Galxe Passport v2.1 | `birthdate:uint<64>; gender:prop<8,c,1>; id_country:prop<16,c,1>; id_class:prop<8,c,1>; document_expiration_date:uint<64>; proof_of_time:uint<64>; last_revoke_time:uint<64>; last_selfie_date:uint<64>; total_sefie_verified:uint<8>` | Your Personal Identifiable Information (PII) after creating your passport [here](https://app.galxe.com/passport) |
Galxe Passport v2.1 type definition contains the following fields:
* `birthdate:uint<64>`: User's birthdate in unix timestamp.
* `gender:prop<8,c,1>`: User's gender, according to their government issued ID.
* Custom hash function mapping:
* Male = 1
* Female = 2
* X = 3 (undermined from government ID)
* `id_country:prop<16,c,1>`: Country of ID issurance.
* Custom hash function mapping:
* ISO-3166-1 Alpha 2 format (2-letter country code) = ISO-3166-1 numeric code
* `id_class:prop<8,c,1>`:
* Custom hash function mapping:
* CertificateOfCitizenship = 1
* ConsularID = 2
* DriversLicense = 3
* ColombiaForeignerID = 4
* CanadaHealthInsuranceCard = 5
* IdentificationCard = 6
* RussiaInternalPassport = 7
* AustraliaKeypassID = 8
* SingaporeLongTermVisitPass = 9
* MunicipalID = 10
* JapanMyNumberCard = 11
* PhilippinesNationalBureauOfInvestigationCertificate = 12
* SingaporeNationalResidencyID = 13
* PhilippinesOverseasForeignWorkerCard = 14
* ResidencePermit = 15
* IndiaPermanentAccountNumberCard = 16
* PhilippinesPostalIdentificationCard = 17
* Passport = 18
* PassportCard = 19
* PermanentResidenceCard = 20
* PhilippinesSocialSecuritySystemCard = 21
* USRefugeeTravelDocument = 22
* CanadaTribalID = 23
* PhilippinesUnitedMultiPurposeID = 24
* VoterID = 25
* ImmigrationVisa = 26
* WorkPermit = 27
* More information can be found here: [https://docs.withpersona.com/reference/government-id-verifications#government-id-types](https://docs.withpersona.com/reference/government-id-verifications#government-id-types)
* `document_expiration_date:uint<64>`: Government ID expiration date in unix timestamp.
* `proof_of_time:uint<64>`: Time delta in Unix timestamp between first and latest verification.
* `last_revoke_time:uint<64>`: Unix timestamp of user's latest Galxe Passport revocation date.
* `last_selfie_date:uint<64>`: Unix timestamp of user's latest Galxe Passport Selfie verification date.
* `total_sefie_verified:uint<8>`: Count of user's successful Selfie Verifications.
### Example signed credential
```json theme={null}
{
"header": {
"version": "1",
"type": "10001",
"context": "238277854774670540602918445255683183190672363274",
"id": ""
},
"body": {
"birthdate": "",
"gender": { "str": "M", "value": "1" },
"id_country": { "str": "US", "value": "840" },
"id_class": { "str": "dl", "value": "3" },
"document_expiration_date": "",
"proof_of_time": "",
"last_revoke_time": "0",
"last_selfie_date": "",
"total_sefie_verified": "1"
},
"signatures": [
{
"metadata": {
"verification_stack": 1,
"signature_id": "",
"expired_at": "",
"identity_commitment": "",
"issuer_id": "278006727486904618205999958244923369060433544",
"chain_id": "97",
"public_key": "GtrdrhiIorbpEkCJb15QN5UgE392xCR1Uhet4A+LLRhaBakE10XuJGktkc90Ql1CcYF+ZOYwEVRp8/KJ0NBrLw=="
},
"signature": "",
"attachmentsSignature": ""
}
],
"attachments": {
"country_code": "US",
"first_verification_date": "",
"passport_version": "v2.1",
"first_name": "",
"birth_date": "",
"sex": "M",
"id_issue_date": "",
"id_expiration_date": "",
"persona_id": "",
"last_name": "",
"nationality": "",
"id_number": "",
"id_class": "dl"
}
}
```
## Passport v2.0
### Type
"Galxe Passport v2" credential type is registered onchain as a custom primitive type with type ID 10000.
| Type ID | Name | Description | Definition | Example |
| ------- | ----------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| 10000 | Galxe Passport v2 | Galxe Passport v2 | `birthdate:uint<64>; gender:prop<8,c,1>; id_country:prop<16,c,1>; id_class:prop<8,c,1>; issue_date:uint<64>; first_verification_date:uint<64>; last_selfie_date:uint<64>; total_sefie_verified:uint<8>` | Your Personal Identifiable Information (PII) after creating your passport [here](https://app.galxe.com/passport) |
Galxe Passport v2 type definition contains the following fields:
* `birthdate:uint<64>`: User's birthdate in unix timestamp.
* `gender:prop<8,c,1>`: User's gender, according to their government issued ID.
* Custom hash function mapping:
* Male = 1
* Female = 2
* X = 3 (undermined from government ID)
* `id_country:prop<16,c,1>`: Country of ID issurance.
* Custom hash function mapping:
* ISO-3166-1 Alpha 2 format (2-letter country code) = ISO-3166-1 numeric code
* `id_class:prop<8,c,1>`:
* Custom hash function mapping:
* CertificateOfCitizenship = 1
* ConsularID = 2
* DriversLicense = 3
* ColombiaForeignerID = 4
* CanadaHealthInsuranceCard = 5
* IdentificationCard = 6
* RussiaInternalPassport = 7
* AustraliaKeypassID = 8
* SingaporeLongTermVisitPass = 9
* MunicipalID = 10
* JapanMyNumberCard = 11
* PhilippinesNationalBureauOfInvestigationCertificate = 12
* SingaporeNationalResidencyID = 13
* PhilippinesOverseasForeignWorkerCard = 14
* ResidencePermit = 15
* IndiaPermanentAccountNumberCard = 16
* PhilippinesPostalIdentificationCard = 17
* Passport = 18
* PassportCard = 19
* PermanentResidenceCard = 20
* PhilippinesSocialSecuritySystemCard = 21
* USRefugeeTravelDocument = 22
* CanadaTribalID = 23
* PhilippinesUnitedMultiPurposeID = 24
* VoterID = 25
* ImmigrationVisa = 26
* WorkPermit = 27
* More information can be found here: [https://docs.withpersona.com/reference/government-id-verifications#government-id-types](https://docs.withpersona.com/reference/government-id-verifications#government-id-types)
* `issue_date:uint<64>`: Government ID issurance date in unix timestamp.
* `first_verification_date:uint<64>`: Unix timestamp of user's first Galxe Passport verification date.
* `last_selfie_date:uint<64>`: Unix timestamp of user's latest Galxe Passport Selfie verification date.
* `total_sefie_verified:uint<8>`: Count of user's successful Selfie Verifications.
Type Artifacts can be found here: [https://ipfs.io/ipfs/QmZ4UghikEohVtpJaiAQorBeHNPFZ9vq5TfnE8jTAyLU9k](https://ipfs.io/ipfs/QmZ4UghikEohVtpJaiAQorBeHNPFZ9vq5TfnE8jTAyLU9k)
### Example signed credential
```json theme={null}
{
"header": {
"version": "1",
"type": "385359061158288630711736738957938254712651867393",
"context": "934334657093539700167251502022510933841607943105",
"id": "1052489016591343323470769874470399378961347062869"
},
"body": {
"birthdate": "",
"gender": {
"str": "M",
"value": "1"
},
"id_country": {
"str": "US",
"value": "840"
},
"id_class": {
"str": "dl",
"value": "3"
},
"issue_date": "",
"first_verification_date": "",
"last_selfie_date": "",
"total_sefie_verified": "1"
},
"signatures": [
{
"metadata": {
"verification_stack": 1,
"signature_id": "174358...",
"expired_at": "",
"identity_commitment": "2025432...",
"issuer_id": "278006...",
"chain_id": "97",
"public_key": "Gtrdr..."
},
"signature": "1+PIQA...",
"attachmentsSignature": "yU8eI8..."
}
],
"attachments": {
"last_name": "Doe",
"id_number": "ID-123456",
"passport_version": "v2.0",
"first_name": "John"
}
}
```
## Issurance Workflow
Once user passes KYC verification with Persona, our KYC provider, upon user request, Galxe backend will:
1. Retrieve all necessary personal identifiable information to issue a Galxe Passport credential.
2. Generate credential using pre-defined type.
3. Append other relevant information as attachments.
4. Galxe-managed issuer sign the credential and its attachments, then add both signatures to the credential.
5. Return the signed credential back to user, and user will encrypt it with their own passport.
6. User store the encrypted file in their preferred storage. For now, user will use Galxe Vault for storage with no charge.
# Ideas
Source: https://docs.galxe.com/identity/use-cases/ideas
### Sybil Prevention
Sybil attack is one of the most prominent attack vectors in the digital space. Currently there is no foolproof solution to prevent sybil attacks. However, the greater amount of identity related data one can access, the easier it becomes to protect sybil attacks.
One solution to protect sybil attacks is through the implementation of KYC (know-your-customer) mechanisms. However, current KYC solutions raise privacy concerns as centralized entities collect and store users’ personal identity information such as address, nationality, name, etc. Galxe Identity Protocol offers a solution to solve this issue by allowing users to have ownership and control over their sensitive identity information. With the Galxe Identity Protocol, users can securely share their data with third parties in a privacy-preserving way using zero-knowledge-proof verification stacks. By empowering users with control over their sensitive information, Galxe Identity Protocol enhances privacy while addressing the need for identity verification in preventing sybil attacks.
Other solutions such as Gitcoin Passport are also effective approaches to tackle sybil attacks. These solutions request and utilize multi-dimension behavior and social data from users to estimate the likelihood of them being real humans and provide quantitative results. However, solutions like Gitcoin Passport typically require each vendor to collect a vast amount of data from users through centralized authentication processes. In contrast, with Galxe Identity Protocol, users’ credentials are aggregated and controlled by the users by default. All developers can thus build such scoring systems without the need to collect additional information from the users.
### Reputation System
Traditional reputation systems often operate independently, resulting in data silos where reputation information is fragmented and not easily portable or shareable between different platforms or services. This lack of interoperability can limit the effectiveness and potential of reputation systems.
Galxe Identity Protocol provides the opportunity to build a decentralized reputation system that can aggregate an individual’s reputation. By utilizing the Galxe Identity Protocol, it becomes possible to create a reputation system that is decentralized, transparent, and secure, enabling reputation to be collected and shared across various platforms or applications. This decentralized approach can enhance the trustworthiness and usability of reputation systems in a more interconnected manner.
### Credit System
Current credit systems often rely on private data, which can raise concerns about data security and privacy. Centralized credit systems typically require access to personal and sensitive information, creating a risk of data breaches or unauthorized access. Additionally, these systems are often permissioned, meaning only certain entities have control over the data and how it is used.
Implementing a permission-less credential protocol can offer several advantages for building a credit system. By leveraging Galxe Identity Protocol, it becomes possible to access a fuller and more diverse dataset for verifying and evaluating creditworthiness. This protocol can enable the integration of data from various sources, allowing for better accuracy and a more comprehensive understanding of an individual's creditworthiness.
### Achievement System
Existing achievement systems often operate independently within specific applications or platforms. This creates data silos where the achievements earned in one application cannot be easily utilized or recognized in other applications. As a result, the value and impact of achievements are limited within their respective ecosystems.
An ideal scenario would be the ability to use achievements across different applications to unlock benefits or gain recognition. If achievements were transferable and recognized across various platforms or applications, it would enhance their value and provide users with tangible benefits beyond individual ecosystems. This would incentivize users to pursue and showcase achievements more actively, fostering a sense of accomplishment and motivation.
### Personal Data Market
In the present scenario, application owners typically have control over users' personal data. They own, share, and may even monetize this information without direct user consent or control. This lack of control raises critical privacy concerns, while depriving users of the opportunities for monetization, and this could even been deemed as a deprivation of users’ assets.
The Galxe Identity Protocol offers a paradigm shift by allowing individuals to regain control over their identity data. With the Galxe Identity Protocol, users can have ownership and agency over their personal credentials. They can decide how their data is used and shared, including the option to exchange data for improved services or monetary incentives. The privacy-enabled verification stack of the Galxe Identity Protocol ensures that users' privacy is protected while engaging in these data transactions.
### Identity Verification
Traditional methods of identity verification, such as presenting physical documents or IDs, are prone to fraud. Methods like photoshopping IDs or faking credentials like education degrees or drivers’ licenses have become increasingly common. These fraudulent practices undermine the reliability and trustworthiness of the verification process.
Issuing digital verifiable credentials can help address these identity fraud concerns. Verifiable credentials are digitally signed pieces of information that are tamper-proof and can be easily verified by relying parties. By issuing these credentials, individuals can securely and conveniently present their verified identity information without the risk of forgery or manipulation.
### Privacy-Enabled Access Control
Many existing access control systems require individuals to disclose private information in order to gain access to certain privileges or events. This can include revealing specific holdings like NFT collections and disclosing personal addresses. These requirements can potentially compromise privacy and expose individuals to risks associated with sharing sensitive information.
By leveraging privacy-enabled verification stacks, it becomes possible to ensure privacy for all kinds of access control systems.
### Decentralized Review System
Credentials in Galxe Identity Protocol go beyond personal identity data and can also include review-like credentials for other individuals or entities such as restaurants, clothing brands, and more. By aggregating reviews for all the entities within the network, developers can build decentralized review systems such as a decentralized version of Yelp. Moreover, the reputation scores built using the protocol can be utilized to weight the review aggregations, resulting in more robust and trustworthy review results.
# LoyaltyPoint
Source: https://docs.galxe.com/loyalty-points/contracts/loyalty-point
The `LoyaltyPoint` contract is the core contract for managing loyalty points. It defines the token logic, including minting and burning points (tokens), as well as role-based access control (RBAC) for managing permissions around minting.
## **Key Features**
* **Minting and Burning** Allows approved minters to mint and burn loyalty points.
* **ERC20 Compatibility** This contract follows the ERC20 token standard, making it interoperable with other blockchain systems.
* **Role-based Access Control (RBAC)** Uses role-based control to assign permissions to mint and burn points.
* **Custom Metadata** Name and symbol for the loyalty point can be customized during deployment.
## **Constructor**
```solidity theme={null}
constructor(
string memory _name,
string memory _symbol,
address _initialAdmin,
address[] memory _minters
)
```
* **\_name** Name of the loyalty point token (e.g., "Galxe Points").
* **\_symbol** Token symbol (e.g., "GP").
* **\_initialAdmin** Admin address responsible for managing permissions.
* **\_minters** An array of addresses with permission to mint points.
## **Role Management**
* The `DEFAULT_ADMIN_ROLE` is given to the `_initialAdmin` address.
* The `MINTER_ROLE` is assigned to any addresses specified in the `_minters` array.
* Admin can add or revoke roles using `grantRole` and `revokeRole`.
## **Minting and Burning**
* **mint()**\
Allows any address with the `MINTER_ROLE` to mint new points.
```solidity theme={null}
function mint(address _to, uint256 _amount) external;
```
* **burn()**\
Allows any address with the `MINTER_ROLE` to burn points from a specified account.
```solidity theme={null}
function burn(address _from, uint256 _amount) external;
```
## **Usage Example**
To mint new loyalty points to a user:
```solidity theme={null}
loyaltyPoint.mint(userAddress, 1000); // Mint 1000 points to userAddress
```
To burn loyalty points from a user:
```solidity theme={null}
loyaltyPoint.burn(userAddress, 500); // Burn 500 points from userAddress
```
## **Custom Events**
* **Mint** Emitted when new points are minted.
* `to`: The address receiving the minted points.
* `amount`: The amount of points minted.
* **Burn** Emitted when points are burned.
* `from`: The address from which points are burned.
* `amount`: The amount of points burned.
## **Security**
* **Pausable** The contract can be paused and unpaused by the admin using the inherited `Pausable` functionality.
* **Access Control** Implements role-based control using OpenZeppelin’s `AccessControl`.
## ABI
```json theme={null}
[
{
"type": "constructor",
"inputs": [
{ "name": "spaceName", "type": "string", "internalType": "string" },
{ "name": "initialAdmin", "type": "address", "internalType": "address" },
{ "name": "minters", "type": "address[]", "internalType": "address[]" }
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "DEFAULT_ADMIN_ROLE",
"inputs": [],
"outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "DOMAIN_SEPARATOR",
"inputs": [],
"outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "MINTER_ROLE",
"inputs": [],
"outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "acceptDefaultAdminTransfer",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "allowance",
"inputs": [
{ "name": "owner", "type": "address", "internalType": "address" },
{ "name": "spender", "type": "address", "internalType": "address" }
],
"outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "approve",
"inputs": [
{ "name": "spender", "type": "address", "internalType": "address" },
{ "name": "value", "type": "uint256", "internalType": "uint256" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "balanceOf",
"inputs": [
{ "name": "account", "type": "address", "internalType": "address" }
],
"outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "beginDefaultAdminTransfer",
"inputs": [
{ "name": "newAdmin", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "burn",
"inputs": [
{ "name": "_user", "type": "address", "internalType": "address" },
{ "name": "_amount", "type": "uint256", "internalType": "uint256" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "burnBatch",
"inputs": [
{ "name": "_users", "type": "address[]", "internalType": "address[]" },
{ "name": "_amounts", "type": "uint256[]", "internalType": "uint256[]" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "cancelDefaultAdminTransfer",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "changeDefaultAdminDelay",
"inputs": [
{ "name": "newDelay", "type": "uint48", "internalType": "uint48" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "decimals",
"inputs": [],
"outputs": [{ "name": "", "type": "uint8", "internalType": "uint8" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "defaultAdmin",
"inputs": [],
"outputs": [{ "name": "", "type": "address", "internalType": "address" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "defaultAdminDelay",
"inputs": [],
"outputs": [{ "name": "", "type": "uint48", "internalType": "uint48" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "defaultAdminDelayIncreaseWait",
"inputs": [],
"outputs": [{ "name": "", "type": "uint48", "internalType": "uint48" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "eip712Domain",
"inputs": [],
"outputs": [
{ "name": "fields", "type": "bytes1", "internalType": "bytes1" },
{ "name": "name", "type": "string", "internalType": "string" },
{ "name": "version", "type": "string", "internalType": "string" },
{ "name": "chainId", "type": "uint256", "internalType": "uint256" },
{
"name": "verifyingContract",
"type": "address",
"internalType": "address"
},
{ "name": "salt", "type": "bytes32", "internalType": "bytes32" },
{ "name": "extensions", "type": "uint256[]", "internalType": "uint256[]" }
],
"stateMutability": "view"
},
{
"type": "function",
"name": "getRoleAdmin",
"inputs": [
{ "name": "role", "type": "bytes32", "internalType": "bytes32" }
],
"outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "grantRole",
"inputs": [
{ "name": "role", "type": "bytes32", "internalType": "bytes32" },
{ "name": "account", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "hasRole",
"inputs": [
{ "name": "role", "type": "bytes32", "internalType": "bytes32" },
{ "name": "account", "type": "address", "internalType": "address" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "mint",
"inputs": [
{ "name": "_user", "type": "address", "internalType": "address" },
{ "name": "_amount", "type": "uint256", "internalType": "uint256" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "mintBatch",
"inputs": [
{ "name": "_users", "type": "address[]", "internalType": "address[]" },
{ "name": "_amounts", "type": "uint256[]", "internalType": "uint256[]" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "name",
"inputs": [],
"outputs": [{ "name": "", "type": "string", "internalType": "string" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "nonces",
"inputs": [
{ "name": "owner", "type": "address", "internalType": "address" }
],
"outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "owner",
"inputs": [],
"outputs": [{ "name": "", "type": "address", "internalType": "address" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "pause",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "paused",
"inputs": [],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "pendingDefaultAdmin",
"inputs": [],
"outputs": [
{ "name": "newAdmin", "type": "address", "internalType": "address" },
{ "name": "schedule", "type": "uint48", "internalType": "uint48" }
],
"stateMutability": "view"
},
{
"type": "function",
"name": "pendingDefaultAdminDelay",
"inputs": [],
"outputs": [
{ "name": "newDelay", "type": "uint48", "internalType": "uint48" },
{ "name": "schedule", "type": "uint48", "internalType": "uint48" }
],
"stateMutability": "view"
},
{
"type": "function",
"name": "permit",
"inputs": [
{ "name": "owner", "type": "address", "internalType": "address" },
{ "name": "spender", "type": "address", "internalType": "address" },
{ "name": "value", "type": "uint256", "internalType": "uint256" },
{ "name": "deadline", "type": "uint256", "internalType": "uint256" },
{ "name": "v", "type": "uint8", "internalType": "uint8" },
{ "name": "r", "type": "bytes32", "internalType": "bytes32" },
{ "name": "s", "type": "bytes32", "internalType": "bytes32" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "renounceRole",
"inputs": [
{ "name": "role", "type": "bytes32", "internalType": "bytes32" },
{ "name": "account", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "revokeRole",
"inputs": [
{ "name": "role", "type": "bytes32", "internalType": "bytes32" },
{ "name": "account", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "rollbackDefaultAdminDelay",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "setName",
"inputs": [
{ "name": "newName", "type": "string", "internalType": "string" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "setSymbol",
"inputs": [
{ "name": "newSymbol", "type": "string", "internalType": "string" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "setTransferable",
"inputs": [
{ "name": "newTransferable", "type": "bool", "internalType": "bool" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "supportsInterface",
"inputs": [
{ "name": "interfaceId", "type": "bytes4", "internalType": "bytes4" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "symbol",
"inputs": [],
"outputs": [{ "name": "", "type": "string", "internalType": "string" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "totalSupply",
"inputs": [],
"outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "transfer",
"inputs": [
{ "name": "to", "type": "address", "internalType": "address" },
{ "name": "value", "type": "uint256", "internalType": "uint256" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "transferFrom",
"inputs": [
{ "name": "from", "type": "address", "internalType": "address" },
{ "name": "to", "type": "address", "internalType": "address" },
{ "name": "value", "type": "uint256", "internalType": "uint256" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "transferable",
"inputs": [],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "unpause",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "event",
"name": "Approval",
"inputs": [
{
"name": "owner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "spender",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"type": "event",
"name": "DefaultAdminDelayChangeCanceled",
"inputs": [],
"anonymous": false
},
{
"type": "event",
"name": "DefaultAdminDelayChangeScheduled",
"inputs": [
{
"name": "newDelay",
"type": "uint48",
"indexed": false,
"internalType": "uint48"
},
{
"name": "effectSchedule",
"type": "uint48",
"indexed": false,
"internalType": "uint48"
}
],
"anonymous": false
},
{
"type": "event",
"name": "DefaultAdminTransferCanceled",
"inputs": [],
"anonymous": false
},
{
"type": "event",
"name": "DefaultAdminTransferScheduled",
"inputs": [
{
"name": "newAdmin",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "acceptSchedule",
"type": "uint48",
"indexed": false,
"internalType": "uint48"
}
],
"anonymous": false
},
{
"type": "event",
"name": "EIP712DomainChanged",
"inputs": [],
"anonymous": false
},
{
"type": "event",
"name": "Paused",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "RoleAdminChanged",
"inputs": [
{
"name": "role",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "previousAdminRole",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "newAdminRole",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
}
],
"anonymous": false
},
{
"type": "event",
"name": "RoleGranted",
"inputs": [
{
"name": "role",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "account",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "sender",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "RoleRevoked",
"inputs": [
{
"name": "role",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "account",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "sender",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "Transfer",
"inputs": [
{
"name": "from",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "to",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"type": "event",
"name": "Unpaused",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{ "type": "error", "name": "AccessControlBadConfirmation", "inputs": [] },
{
"type": "error",
"name": "AccessControlEnforcedDefaultAdminDelay",
"inputs": [
{ "name": "schedule", "type": "uint48", "internalType": "uint48" }
]
},
{
"type": "error",
"name": "AccessControlEnforcedDefaultAdminRules",
"inputs": []
},
{
"type": "error",
"name": "AccessControlInvalidDefaultAdmin",
"inputs": [
{ "name": "defaultAdmin", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "AccessControlUnauthorizedAccount",
"inputs": [
{ "name": "account", "type": "address", "internalType": "address" },
{ "name": "neededRole", "type": "bytes32", "internalType": "bytes32" }
]
},
{ "type": "error", "name": "ECDSAInvalidSignature", "inputs": [] },
{
"type": "error",
"name": "ECDSAInvalidSignatureLength",
"inputs": [
{ "name": "length", "type": "uint256", "internalType": "uint256" }
]
},
{
"type": "error",
"name": "ECDSAInvalidSignatureS",
"inputs": [{ "name": "s", "type": "bytes32", "internalType": "bytes32" }]
},
{
"type": "error",
"name": "ERC20InsufficientAllowance",
"inputs": [
{ "name": "spender", "type": "address", "internalType": "address" },
{ "name": "allowance", "type": "uint256", "internalType": "uint256" },
{ "name": "needed", "type": "uint256", "internalType": "uint256" }
]
},
{
"type": "error",
"name": "ERC20InsufficientBalance",
"inputs": [
{ "name": "sender", "type": "address", "internalType": "address" },
{ "name": "balance", "type": "uint256", "internalType": "uint256" },
{ "name": "needed", "type": "uint256", "internalType": "uint256" }
]
},
{
"type": "error",
"name": "ERC20InvalidApprover",
"inputs": [
{ "name": "approver", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "ERC20InvalidReceiver",
"inputs": [
{ "name": "receiver", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "ERC20InvalidSender",
"inputs": [
{ "name": "sender", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "ERC20InvalidSpender",
"inputs": [
{ "name": "spender", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "ERC2612ExpiredSignature",
"inputs": [
{ "name": "deadline", "type": "uint256", "internalType": "uint256" }
]
},
{
"type": "error",
"name": "ERC2612InvalidSigner",
"inputs": [
{ "name": "signer", "type": "address", "internalType": "address" },
{ "name": "owner", "type": "address", "internalType": "address" }
]
},
{ "type": "error", "name": "EnforcedPause", "inputs": [] },
{ "type": "error", "name": "ExpectedPause", "inputs": [] },
{
"type": "error",
"name": "InvalidAccountNonce",
"inputs": [
{ "name": "account", "type": "address", "internalType": "address" },
{ "name": "currentNonce", "type": "uint256", "internalType": "uint256" }
]
},
{ "type": "error", "name": "InvalidAddress", "inputs": [] },
{ "type": "error", "name": "InvalidShortString", "inputs": [] },
{ "type": "error", "name": "ParamsLengthMismatch", "inputs": [] },
{ "type": "error", "name": "PermissionDenied", "inputs": [] },
{
"type": "error",
"name": "SafeCastOverflowedUintDowncast",
"inputs": [
{ "name": "bits", "type": "uint8", "internalType": "uint8" },
{ "name": "value", "type": "uint256", "internalType": "uint256" }
]
},
{ "type": "error", "name": "SetTransferableNotAllowed", "inputs": [] },
{
"type": "error",
"name": "StringTooLong",
"inputs": [{ "name": "str", "type": "string", "internalType": "string" }]
},
{ "type": "error", "name": "TransferNotAllow", "inputs": [] }
]
```
# LoyaltyPointFactory
Source: https://docs.galxe.com/loyalty-points/contracts/loyalty-point-factory
The `LoyaltyPointFactory` contract is responsible for deploying new instances of the `LoyaltyPoint` contract. It serves as a factory pattern for creating customizable loyalty point tokens with specific configurations.
## **Addresses**
Gravity Alpha Testnet Sepolia: [0x8a85eC5AE1ae2c757eEfBb10b1203C984120bf8c](https://explorer-sepolia.gravity.xyz/address/0x8a85eC5AE1ae2c757eEfBb10b1203C984120bf8c)
Gravity Alpha Mainnet: [0xd7B8c5f22f3589842f481EEb2d4F1F2f8CFc2038](https://explorer.gravity.xyz/address/0xd7B8c5f22f3589842f481EEb2d4F1F2f8CFc2038)
## **Key Features**
* **Role Management** Admin rights are granted to a specified initial admin.
* **Pause/Unpause Functionality** Provides the ability to pause and unpause contract functions for security and maintenance.
* **Salted Deployment** Uses `create2` to ensure deterministic contract addresses based on provided salt.
## **Constructor**
```solidity theme={null}
constructor(address _initialAdmin)
```
* **\_initialAdmin**: This is the address assigned as the administrator of the contract and any loyalty point contracts created by it.
* The constructor checks whether the provided admin address is valid (i.e., non-zero). If the address is invalid, the contract throws an `InvalidAddress()` error.
## **Events**
* **CreateLoyaltyPoint** Emitted when a new `LoyaltyPoint` contract is created.
* `loyaltyPoint`: The address of the newly deployed `LoyaltyPoint` contract.
* `name`: The name of the loyalty point token (e.g., "Galxe Points").
* `symbol`: The symbol of the loyalty point token (e.g., "GP").
* `initialAdmin`: The address that will serve as the admin of the new loyalty point contract.
* `minters`: An array of addresses that have the permission to mint loyalty points.
## **Key Functions**
* **pause() / unpause()**\
These functions allow the owner to pause or unpause contract execution for security purposes.
```solidity theme={null}
function pause() public onlyOwner;
function unpause() public onlyOwner;
```
* **createLoyaltyPoint()**\
This function deploys a new instance of the `LoyaltyPoint` contract using the `create2` opcode, which allows for a deterministic address based on the contract's salt (a hash of the name and symbol). The initial admin and minting addresses are also passed to the new contract.
**Parameters**
* `_name`: The name of the loyalty point token.
* `_symbol`: The symbol for the loyalty point token.
* `_initialAdmin`: The admin address for the new contract.
* `_minters`: An array of addresses that will have permission to mint tokens in the new contract.
**Returns**
* `contractAddr`: The address of the newly created loyalty point contract.
**Code Example**
```solidity theme={null}
function createLoyaltyPoint(
string calldata _name,
string calldata _symbol,
address _initialAdmin,
address[] memory _minters
) external whenNotPaused returns (address contractAddr);
```
## **Usage Example**
To create a new loyalty point token:
```solidity theme={null}
address newLoyaltyPoint = factory.createLoyaltyPoint("Galxe Points", "GP", adminAddress, [minterAddress1, minterAddress2]);
```
## ABI
```json theme={null}
[
{
"type": "constructor",
"inputs": [
{ "name": "_initialAdmin", "type": "address", "internalType": "address" },
{ "name": "_signer", "type": "address", "internalType": "address" }
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "acceptOwnership",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "createLoyaltyPoint",
"inputs": [
{ "name": "_spaceID", "type": "uint64", "internalType": "uint64" },
{ "name": "_version", "type": "string", "internalType": "string" },
{ "name": "_spaceName", "type": "string", "internalType": "string" },
{ "name": "_initialAdmin", "type": "address", "internalType": "address" },
{ "name": "_minters", "type": "address[]", "internalType": "address[]" },
{ "name": "_signature", "type": "bytes", "internalType": "bytes" }
],
"outputs": [
{ "name": "contractAddr", "type": "address", "internalType": "address" }
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "eip712Domain",
"inputs": [],
"outputs": [
{ "name": "fields", "type": "bytes1", "internalType": "bytes1" },
{ "name": "name", "type": "string", "internalType": "string" },
{ "name": "version", "type": "string", "internalType": "string" },
{ "name": "chainId", "type": "uint256", "internalType": "uint256" },
{
"name": "verifyingContract",
"type": "address",
"internalType": "address"
},
{ "name": "salt", "type": "bytes32", "internalType": "bytes32" },
{ "name": "extensions", "type": "uint256[]", "internalType": "uint256[]" }
],
"stateMutability": "view"
},
{
"type": "function",
"name": "getLoyaltyPoint",
"inputs": [
{ "name": "_spaceID", "type": "uint64", "internalType": "uint64" }
],
"outputs": [{ "name": "", "type": "address", "internalType": "address" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "loyaltyPointContracts",
"inputs": [{ "name": "", "type": "uint64", "internalType": "uint64" }],
"outputs": [{ "name": "", "type": "address", "internalType": "address" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "owner",
"inputs": [],
"outputs": [{ "name": "", "type": "address", "internalType": "address" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "pause",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "paused",
"inputs": [],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "pendingOwner",
"inputs": [],
"outputs": [{ "name": "", "type": "address", "internalType": "address" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "renounceOwnership",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "setSigner",
"inputs": [
{ "name": "_signer", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "signer",
"inputs": [],
"outputs": [{ "name": "", "type": "address", "internalType": "address" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "transferOwnership",
"inputs": [
{ "name": "newOwner", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "unpause",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "event",
"name": "CreateLoyaltyPoint",
"inputs": [
{
"name": "loyaltyPoint",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "spaceID",
"type": "uint64",
"indexed": false,
"internalType": "uint64"
},
{
"name": "version",
"type": "string",
"indexed": false,
"internalType": "string"
},
{
"name": "spaceName",
"type": "string",
"indexed": false,
"internalType": "string"
},
{
"name": "initialAdmin",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "minters",
"type": "address[]",
"indexed": false,
"internalType": "address[]"
}
],
"anonymous": false
},
{
"type": "event",
"name": "EIP712DomainChanged",
"inputs": [],
"anonymous": false
},
{
"type": "event",
"name": "OwnershipTransferStarted",
"inputs": [
{
"name": "previousOwner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newOwner",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "OwnershipTransferred",
"inputs": [
{
"name": "previousOwner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newOwner",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "Paused",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "Unpaused",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{ "type": "error", "name": "ECDSAInvalidSignature", "inputs": [] },
{
"type": "error",
"name": "ECDSAInvalidSignatureLength",
"inputs": [
{ "name": "length", "type": "uint256", "internalType": "uint256" }
]
},
{
"type": "error",
"name": "ECDSAInvalidSignatureS",
"inputs": [{ "name": "s", "type": "bytes32", "internalType": "bytes32" }]
},
{ "type": "error", "name": "EnforcedPause", "inputs": [] },
{ "type": "error", "name": "ExpectedPause", "inputs": [] },
{ "type": "error", "name": "InvalidAddress", "inputs": [] },
{ "type": "error", "name": "InvalidShortString", "inputs": [] },
{ "type": "error", "name": "InvalidSignature", "inputs": [] },
{
"type": "error",
"name": "OwnableInvalidOwner",
"inputs": [
{ "name": "owner", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "OwnableUnauthorizedAccount",
"inputs": [
{ "name": "account", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "StringTooLong",
"inputs": [{ "name": "str", "type": "string", "internalType": "string" }]
}
]
```
# API
Source: https://docs.galxe.com/loyalty-points/getting-started/api
For all Loyalty Point contract deployed via our factory on Gravity chains, we provide the following GraphQL API to query the leaderboard:
* Endpoint: [https://graphigo-business.prd.galaxy.eco/query](https://graphigo-business.prd.galaxy.eco/query)
* Playground: [https://graphigo-business.prd.galaxy.eco](https://graphigo-business.prd.galaxy.eco)
## Example
Here is an example of how to query the API:
```graphql theme={null}
query {
loyaltyPointLeaderboard(
loyaltyPointAddress: "0x6B08B2fC665F766193A0cB9a64bcfB8beaac03D4"
limit: 10
) {
totalCount
list {
address
points
rank
}
}
}
```
## Example Response
```json theme={null}
{
"data": {
"loyaltyPointLeaderboard": {
"totalCount": 1,
"list": [
{
"address": "0xb85b3d61439a3d70d3df7913a3a764f352b32c55",
"points": 1,
"rank": 1
}
]
}
}
}
```
You can use cursor to paginate through the leaderboard.
# Hook
Source: https://docs.galxe.com/loyalty-points/getting-started/hook
Hooks are functions that can be added to the Loyalty Point contract to extend its functionality. They are executed during token transfers and can be used to implement custom logic, such as access control, rewards distribution, or external event triggers.
## Creating a Hook
To create a hook, you need to implement the `ILoyaltyPointHook` interface:
```solidity theme={null}
interface ILoyaltyPointHook {
function onUpdate(address from, address to, uint256 value) external returns (bool);
}
```
Now let's see how to create a hook and add it to your Loyalty Point contract. For this example, we'll create a hook that will trigger an event when user points are updated.
```solidity theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "../interface/ILoyaltyPointHook.sol"; // Adjust the path as necessary
contract ExampleLoyaltyPointHook is ILoyaltyPointHook {
// Event emitted when points are updated
event PointsUpdated(
address indexed from,
address indexed to,
uint256 value
);
// Implementing the onUpdate function
function onUpdate(
address from,
address to,
uint256 value
) external override returns (bool) {
// Emit the PointsUpdated event
emit PointsUpdated(from, to, value);
return true; // Indicate success
}
}
```
## Deploying the Hook
Set up the environment variables:
```bash theme={null}
PRIVATE_KEY=
```
Deploy the hook:
```bash theme={null}
forge script script/DeployExampleLoyaltyPointHook.s.sol:DeployExampleLoyaltyPointHook --rpc-url --broadcast
```
## Setup hook on Loyalty Point contract
Set up necessary environment variables:
```bash theme={null}
PRIVATE_KEY=
LOYALTY_POINT_ADDRESS=
HOOK_ADDRESS=
```
* `PRIVATE_KEY`: The private key of the admin account of the Loyalty Point contract.
* `LOYALTY_POINT_ADDRESS`: The address of the Loyalty Point contract.
* `HOOK_ADDRESS`: The address of the hook contract.
Add the hook to the Loyalty Point contract:
```bash theme={null}
forge script script/AddHook.s.sol:AddHook --rpc-url --broadcast
```
## Testing the Hook
You can test the hook by minting or burning points to a user. The hook should be triggered and the event should be emitted.
## Example
An example of a hook that distributes rewards to a user has been deployed [here](https://explorer-sepolia.gravity.xyz/address/0xf385b659DD1B6785d4FDf83E34Ee228d2Fb10281).
And here is a transaction that triggers the hook: [0xa4d01f742a1f532cecdb3b0c0a1a3b0922603cec4cf0edf46bd00c549ad03b75](https://explorer-sepolia.gravity.xyz/tx/0xa4d01f742a1f532cecdb3b0c0a1a3b0922603cec4cf0edf46bd00c549ad03b75).
In the transaction logs, you can see that the hook is called and the `PointsUpdated` event is emitted.
# Galxe Loyalty Points
Source: https://docs.galxe.com/loyalty-points/getting-started/introduction
The Galxe Loyalty Point System is an on-chain solution designed for the creation, distribution, and management of loyalty points. The system leverages blockchain technology to offer transparency, immutability, and security, providing projects and developers with an efficient way to engage users through loyalty programs.
This system allows loyalty point issuers (such as brands or event organizers) to create custom loyalty point tokens that are fully verifiable and transferable on-chain. By interacting with this system, users can earn, transfer, and manage their loyalty points seamlessly, with full control over token issuance and burning.
## Core Features
1. Customizable Loyalty Point Contracts
Loyalty points are represented as ERC-20 tokens, which can be customized by the issuer. Each loyalty point contract is created using the factory method and is managed by a designated admin.
The contract supports:
* Minting and burning of loyalty points for individual users or in batches.
* Custom token names and symbols, which can be updated as needed.
* Transferability options, allowing the admin to control whether tokens can be transferred between users.
2. Minting & Burning Mechanism
Loyalty points are issued (minted) by entities with the `MINTER_ROLE` and can be burned by the same. This ensures that only authorized entities can control the issuance and removal of points. Minting and burning can be done individually or in batches, allowing for flexibility in managing large groups of users.
3. Transferability Control
Admins have the ability to toggle the transferability of loyalty points. By default, points are non-transferable, but this setting can be changed by the admin. This feature is useful for programs where points can only be redeemed but not traded or transferred between users.
4. Hooks for Custom Logic
The Loyalty Point contract allows for the integration of custom logic through Hooks. These hooks can be used to introduce additional functionality, such as access control, rewards distribution, or external event triggers. Admins can add or remove hooks, which are executed during token transfers.
5. Pausable Contract
To ensure security and flexibility, the contract is pausable. Admins can pause or unpause the contract, freezing all token transactions during maintenance or in case of security issues. This feature is integrated using OpenZeppelin’s ERC20Pausable extension.
## Use Cases
* Retail Loyalty Programs: Brands can issue loyalty points that are awarded based on customer activities such as purchases, reviews, or engagement. The points can be redeemed for discounts, rewards, or exclusive access, with full control over how they are managed.
* Event Ticketing & Rewards: Event organizers can create loyalty points to reward attendees for participation, early registration, or referrals. Points can be used for priority access, VIP services, or redeemable rewards during the event.
* Gaming & Competition: Game developers can issue points for in-game achievements, which can later be redeemed for in-game assets or advantages. The leaderboard system can be integrated to track top players and enhance competition.
* Community Engagement: Communities can use loyalty points to reward members for participation, content creation, or contributions. These points can then be redeemed for recognition, special roles, or other benefits within the community.
# Quick Start
Source: https://docs.galxe.com/loyalty-points/getting-started/quick-start
This quick start guide will walk you through deploying and interacting with your own LoyaltyPoint contract. Follow the steps below to set up your loyalty points system quickly.
# **Prerequisites**
Before you begin, ensure you have the following tools and dependencies installed:
* **Foundry**: Install Foundry by following the instructions at [https://book.getfoundry.sh/getting-started/installation](https://book.getfoundry.sh/getting-started/installation)
# **Contract Deployment**
## **Step 1: Clone the Repository**
```bash theme={null}
git clone https://github.com/galxe/loyalty-point.git
cd loyalty-point
```
## **Step 2: Install Dependencies**
```bash theme={null}
forge install
```
## **Step 3: Compile Contracts**
```bash theme={null}
forge build
```
## **Step 4: Deploy your own LoyaltyPoint**
Set up necessary environment variables:
```bash theme={null}
FACTORY_ADDRESS=
PRIVATE_KEY=
OWNER=
MINTER=
```
* `FACTORY_ADDRESS` is the address of the deployed LoyaltyPointFactory contract on the network you are deploying to. For example, on Gravity Alpha Testnet Sepolia, the factory address is `0x8a85eC5AE1ae2c757eEfBb10b1203C984120bf8c`.
* `PRIVATE_KEY` is the private key of the owner address.
* `OWNER` is the owner address of the LoyaltyPoint contract.
* `MINTER` is the minter address of the LoyaltyPoint contract.
Run the deployment script:
```bash theme={null}
forge script script/DeployLoyaltyPoint.s.sol:DeployLoyaltyPoint --rpc-url --broadcast
```
* `rpc-url` is the RPC URL of the network you are deploying to. For example, on Gravity Alpha Testnet Sepolia, the RPC URL is `https://rpc-sepolia.gravity.xyz`.
* Example deployed contract: [0x6B08B2fC665F766193A0cB9a64bcfB8beaac03D4](https://explorer.gravity.xyz/address/0x6b08b2fc665f766193a0cb9a64bcfb8beaac03d4?tab=txs)
# **Interacting with the LoyaltyPoint Contract**
## **Mint Loyalty Points to user**
Using the `MINTER` address, you can mint loyalty points to a user:
Set up necessary environment variables:
```bash theme={null}
PRIVATE_KEY=
LOYALTY_POINT_ADDRESS=
USER_ADDRESS=
```
* `PRIVATE_KEY` is the private key of the MINTER address.
* `LOYALTY_POINT_ADDRESS` is the address of the deployed LoyaltyPoint contract.
* `USER_ADDRESS` is the address of the user to mint points to.
Run the minting script:
```bash theme={null}
forge script script/MintLoyaltyPoint.s.sol:MintLoyaltyPoint --rpc-url --broadcast
```
* Example mint transaction: [https://explorer.gravity.xyz/tx/0xc45af104acfc9f33df4a3ab877e114441113ad77cedb7044b789dad506970ac5](https://explorer.gravity.xyz/tx/0xc45af104acfc9f33df4a3ab877e114441113ad77cedb7044b789dad506970ac5)
# **Conclusion**
You've successfully deployed your loyalty points system! The LoyaltyPoint contract provides a robust system for minting, burning, and controlling loyalty points for your users, while the factory allows for easy contract creation and management.
Continue by integrating the contracts with your frontend or dApp to offer a seamless user experience.
# Config
Source: https://docs.galxe.com/quest/credential-api/api-cred/config
Learn how to configure API Credential.
## Overview
API credentials allow you to push user data to Galxe via the API, suitable for simple use cases such as whitelist checks.
If you want to understand the workflow and considerations of API credentials, please refer to the [introduction](/quest/credential-api/api-cred/introduction)
***
## Config process
### 1. Finding the Config in Task Settings
The option to configure API credential can be found in step 3, [Task Settings](https://help.galxe.com/en/articles/9728885-create-quest-tasks-settings) of quest creation on the Galxe Dashboard, under the `Import Your Own Data `task type.
### 2. Basic Config
* **ID Type**
`ID Type` provides various identity options, including social accounts, blockchain addresses, and other unique identifiers. Choose the one appropriate to your task.
* **Title**
Give your credential a descriptive title relevant to the task at hand.
* **Credential Source**
Choose `API` type
* **Description**:
Description of the task, supports rich text input, maximum 200 characters.
* **Call-to-Action Link**:
Guide users to the specific URL where they can complete the task.
* **Participation End Time(Optional)**:
Control the time range of the credential, prohibiting new verifications after the deadline.
* **Update Frequency (Optional)**:
Remind users of the frequency of API data source updates, such as once a day or once every two days.
### 3. API Update
Use the [Galxe GraphQL API](https://docs.galxe.com/quest/graphql-api/credential/mutations/credential-holder-update) to push data to the credential.
* **GraphQL Example**:
```cs theme={null}
mutation {
credentialItems(
input: {
credId: "312"
operation: APPEND
items: [
"0x111fd6240381af2c5f1a9e27f282bae8b92b257"
"0x222dde76Cf5752f2bc1DC798BA1369dcA49d7c79"
"0x333eC1a5d0BC3C4291aeb962CBda49677E9a9FcB"
"0x444022af64bfc0f59ce1069e4ab51aa15148e60b"
"0x55526ef96b12fba7a507afba39bdfc78e0039742"
"0x6662c6b59e87b302b43400303427acd50f8071e6"
"0x777742ee649ee36edcf5ac9a97df34333a97fd24"
"0x8886b92fda46b8d9d33ca28d8837e1661edf8b97"
"0x999886e265cf2ec39f8868d7b6c67ab78e027736"
]
}
) {
eligible(address:"0x999886e265cf2ec39f8868d7b6c67ab78e027736")
}
}
```
* **Code Examples**:
```curl cURL theme={null}
curl 'https://graphigo-business.prd.galaxy.eco/query' \
-H 'access-token: YOUR-ACCESS-TOKEN' \
-H 'content-type: application/json' \
--data-raw '{"query":"mutation {\n credentialItems(\n input: {\n credId: \"312\"\n operation: APPEND\n items: [\n \"0x111fd6240381af2c5f1a9e27f282bae8b92b257\"\n \"0x222dde76Cf5752f2bc1DC798BA1369dcA49d7c79\"\n \"0x333eC1a5d0BC3C4291aeb962CBda49677E9a9FcB\"\n \"0x444022af64bfc0f59ce1069e4ab51aa15148e60b\"\n \"0x55526ef96b12fba7a507afba39bdfc78e0039742\"\n \"0x6662c6b59e87b302b43400303427acd50f8071e6\"\n \"0x777742ee649ee36edcf5ac9a97df34333a97fd24\"\n \"0x8886b92fda46b8d9d33ca28d8837e1661edf8b97\"\n \"0x999886e265cf2ec39f8868d7b6c67ab78e027736\"\n ]\n }\n ) {\n eligible(address:\"0x999886e265cf2ec39f8868d7b6c67ab78e027736\")\n }\n}\n\n"}'
```
```javascript JavaScript theme={null}
const axios = require("axios");
const credId = "123";
const operation = "APPEND";
const items = ["0x123"];
(async () => {
try {
let result = await axios.post(
"https://graphigo-business.prd.galaxy.eco/query",
{
operationName: "credentialItems",
query: `
mutation credentialItems($credId: ID!, $operation: Operation!, $items: [String!]!) {
credentialItems(input: { credId: $credId, operation: $operation, items: $items }) {
name
}
}
`,
variables: {
credId: credId, // Ensure it's a string to avoid overflow
operation: operation,
items: items,
},
},
{
headers: {
"access-token": "access-token-of-yours",
},
}
);
if (result.status != 200) {
throw new Error(result);
} else if (result.data.errors && result.data.errors.length > 0) {
console.error(result.data.errors);
throw new Error(result.data.errors);
} else {
console.log("Success:", result.data.data.credentialItems);
}
} catch (error) {
console.error("Error:", error);
}
})();
```
```go Go theme={null}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://graphigo-business.prd.galaxy.eco/query"
accessToken := "access-token-of-yours"
// Request payload
payload := map[string]interface{}{
"operationName": "credentialItems",
"query": `
mutation credentialItems($credId: ID!, $operation: Operation!, $items: [String!]!) {
credentialItems(input: { credId: $credId, operation: $operation, items: $items }) {
name
}
}
`,
"variables": map[string]interface{}{
"credId": "123", // Ensure it's a string
"operation": "APPEND",
"items": []string{"0x123"},
},
}
// Convert payload to JSON
payloadBytes, err := json.Marshal(payload)
if err != nil {
fmt.Println("Error marshalling payload:", err)
return
}
// Create HTTP request
req, err := http.NewRequest("POST", url, bytes.NewBuffer(payloadBytes))
if err != nil {
fmt.Println("Error creating request:", err)
return
}
// Add headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("access-token", accessToken)
// Send HTTP request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
// Read response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response:", err)
return
}
// Parse response
var result map[string]interface{}
err = json.Unmarshal(body, &result)
if err != nil {
fmt.Println("Error unmarshalling response:", err)
return
}
// Check for errors
if errors, ok := result["errors"]; ok {
fmt.Println("GraphQL Errors:", errors)
} else {
fmt.Println("Success:", result["data"])
}
}
```
```java Java theme={null}
const credId = "123";
const operation = "APPEND";
const items = ["0x123"];
// Nodejs using Axios lib
let result = await axios.post("https://graphigo-business.prd.galaxy.eco/query", {
operationName: "credentialItems",
query: `
mutation credentialItems($credId: ID!, $operation: Operation!, $items: [String!]!)
{
credentialItems(input: {
credId: $credId
operation: $operation
items: $items
})
{
name
}
}
`,
variables: {
// Make sure this is string type as int might cause overflow
credId: credId,
operation: operation,
items: items
},
},
{
headers: {
"access-token": "access-token-of-yours",
}
}
);
if (result.status != 200) {
throw new Error(result);
} else if (result.errors && result.errors.length > 0) {
// NOTE: GraphQL returns 200 even if there's an error,
// so must explicitly check result.errors.
console.log(result.errors);
throw new Error(result.errors);
}
```
# Introduction
Source: https://docs.galxe.com/quest/credential-api/api-cred/introduction
Galxe API allows for dynamic management of who can verify tasks in your quest by adding, removing, or replacing user lists in credential data directly. It is designed for scenarios that require real-time updates, making it ideal for managing user access, eligibility, or participation in quests.
***
## Requirements
* **Access Token**: Obtain an [access-token](https://help.galxe.com/en/articles/9733866-introducing-galxe-account#h_3b839618dd) bound to your wallet address for authentication.
* **Permissions**: Ensure your wallet address has [admin or owner access](https://help.galxe.com/en/articles/8506982-getting-started-with-galxe-quest#h_a7571f6cb9) to the space where the credential resides.
* **Rate Limits**: For large request volumes, contact Galxe to whitelist your external IP and avoid rate-limit issues.
***
## Core Operations
* **APPEND**: Add new items (e.g., addresses or emails) to an existing list.
* **REMOVE**: Remove specific items from the list.
* **REPLACE**: Replace the entire list (recommended only for small data sets, e.g., less than 500 entries).
***
## Interaction Method
* API operations are performed using **GraphQL mutations**, allowing flexible and efficient data updates.
* Eligibility of users is evaluated through responses processed by JavaScript expressions, returning `1` (eligible) or `0` (not eligible).
***
## Use Cases
* **Campaign Management**: Dynamically update user data for specific tasks in quests.
* **Real-Time Validation**: Verify and update user credentials, such as wallet addresses or emails.
* **Batch Updates**: Modify credential lists for rewards distribution, permissions, or event participation.
***
## Notes
* **REPLACE Usage**: Suitable for small-scale updates; for large lists, use REMOVE followed by APPEND.
* **Retry Mechanism**: Always retry requests on errors. APPEND and REMOVE operations are idempotent and safe for repeated attempts.
* **Rate Limits**: Monitor API usage to avoid `429` errors, and contact Galxe for whitelisting if necessary.
# Config
Source: https://docs.galxe.com/quest/credential-api/contract-query-cred/config
Learn how to configure Contract Query Credential
## Overview
The Contract Query credential utilizes the blockchain’s standard RPC interface to enable precise retrieval of user interactions with smart contracts, facilitating further analysis and validation.
## If you want to understand the workflow and considerations of Contract Query credentials, please refer to the [introduction](/quest/credential-api/contract-query-cred/introduction)
## Config process
### 1. Title
Set an engaging title for your credential.
### 2. Select Chain
Select the blockchain network to interact with (such as Ethereum, Polygon, BSC, and other EVM-compatible chains supported by Galxe).
If you use a `Customized RPC` (EVM-compatible required), please pay attention to the [CORS Check](/quest/credential-api/overview/cross-domain-check).
### 3. Contract Address & ABI
When selecting a network supported by Galxe, after entering the correct contract address, the ABI will be automatically recognized and filled in.
Enter the address of the `smart contract` and its `ABI` (Application Binary Interface).
### 4. Selcet Method
Select the method to be called from the smart contract's ABI.
### 5. Snapshot()
Take a snapshot to capture the data state at a specific point in time, effectively defending against Sybil attacks.
### 6. Test Response
Enter an address and test to see if the return result meets expectations.
### 7. Description
Description of the certificate, supports rich text input, maximum 200 characters.
### 8. Call-to-Action Link
Guide users to specific operation pages to complete interactive tasks.
***
# Introduction
Source: https://docs.galxe.com/quest/credential-api/contract-query-cred/introduction
## Overview
**Contract Query Credentials** allow you to fetch on-chain data from smart contracts to verify user eligibility. By specifying the blockchain network, contract address, and method to call, Galxe dynamically queries the data and evaluates results to determine if users meet the credential conditions.
***
## Key Features
1. **Chain Selection**:
* Choose a blockchain network (e.g., Ethereum, Polygon, or Binance Smart Chain).
* For unsupported networks or private chains, use **Customized RPC**.
When using **Customized RPC**, ensure that the RPC endpoint is compatible with the changes introduced in [go-ethereum v1.13.0](https://github.com/ethereum/go-ethereum/issues/28608), where `eth_call` requests must use the `input` field instead of the `data` field.
2. **Contract ABI and Address**:
* Provide the smart contract's ABI (Application Binary Interface).
* Specify the **contract address** where the query will be sent.
3. **Method Selection**:
* Choose the specific method to call from the contract’s ABI.
* Pass the user’s wallet address as a parameter.
4. **Snapshot Feature**:
* Use the **Snapshot** feature to lock the query at a specific block height, ensuring data consistency.
5. **Real-Time Testing**:
* Use the **Test Response** section to send test queries and validate the results.
***
## Workflow
1. **Define Credential Title**:
* Enter a descriptive title to clearly indicate the purpose of the credential.
2. **Choose Blockchain Network**:
* Select a supported chain or provide a customized RPC endpoint.
3. **Provide Contract Details**:
* Input the target smart contract’s address and paste its ABI.
* Select the method to call and define relevant parameters.
4. **Test Configuration**:
* Simulate the query using a test address and confirm the response meets expectations.
5. **Deploy and Use**:
* Save and integrate the credential into your campaign to verify user eligibility based on on-chain data.
***
## Contract Method Requirements
To use Contract Query Credentials in Galxe, your smart contract methods must meet the following requirements for ABI-based queries:
1. **stateMutability: view**
* **Requirement**: The method must be declared as `view`.
* **Reason**: Galxe only calls read-only methods, which do not modify the blockchain state.
* **Use Case**: Retrieve on-chain data like token balances, NFT ownership, or staking status.
* **Advantage**: No gas fee required for direct calls (off-chain queries only).
2. **type: function**
* **Requirement**: The method must be a standard callable function (`function`).
* **Reason**: Galxe queries functions via ABI and only supports standard function types.
* **Note**: Constructors or other special function types are not supported.
3. **input: address**
* **Requirement**: The method must accept an address (`address`) as a dynamic input parameter.
* **Use Case**: The address typically identifies the user's wallet, a smart contract, or the owner of an asset.
* **Functionality**: This parameter allows Galxe to query specific address-related data or validate logic.
Example ABI:
```json theme={null}
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
```
***
## Example Use Cases
* **NFT Ownership Verification**:
* Use the `balanceOf` method in ERC-721 contracts to verify if a user holds a specific NFT.
* **Token Holding Requirements**:
* Use the `balanceOf` method in ERC-20 contracts to verify if a user holds a certain amount of tokens.
When querying this method, ensure the `Output Parameter` includes `Decimals` to avoid incorrect balance displays.
* **Custom Logic**:
* Check for more complex conditions, such as staking, governance participation, or other contract interactions.
***
## Notes
* **Snapshot Feature**: Execute queries at a specific block height, useful for checking data at a specific point in time.
If the snapshot is not enabled and the credential queries transferable tokens, there is a Sybil-attack risk. A user could transfer tokens to multiple addresses and claim multiple rewards from a single campaign.
* **Testing**: Always validate your setup in the "Test Response" section before deployment.
* **RPC Configuration**: Ensure the selected chain or RPC endpoint is reliable, accessible, and compliant with Galxe's [CORS Check](/quest/credential-api/overview/cross-domain-check) standards.
# Introduction
Source: https://docs.galxe.com/quest/credential-api/graphql-cred/introduction
`GraphQL` credentials let Galxe fetch data from your authorized GraphQL endpoint, including `Subgraph` endpoints. During user verification, Galxe sends a query with the user’s address to the endpoint. The response is evaluated by a `JavaScript(ES6)` expression, returning `1` (eligible) or `0` (not eligible).
***
### **Workflow**
1. **app.galxe.com**: When a user clicks "Verify" on the Quest page, Galxe sends the user's wallet address or other social media information as an input parameter.
2. **Galxe Backend**: Based on the pre-configuration, Galxe sends an HTTP request containing the wallet address to your `GraphQL API` and waits for the response.
3. **Your Backend**: After receiving the HTTP request from Galxe, your backend processes the request and returns the response data related to the wallet address.
4. **Galxe Backend**: Processes the `response.body` from your backend using predefined expressions to determine if the user meets the conditions.
`35.185.209.0` and `35.203.155.18` are our outbound IPs. Failure to whitelist these may result in 403 errors when accessing the service.
***
### **Configuration Requirements**
**API Specification**
* **Endpoint**:
The URL of the `GraphQL` endpoint.
We only support the default ports for HTTP and HTTPS (80 and 443).
* **(Optional) Headers**:
`Key-value` pairs included in the `GraphQL` request.
* **Query Info**:
Fill in the actual query logic within the `{}` of the pre-filled template, for example:
```graphql theme={null}
query info($address: String!) {
user(address: $address) {
isWhitelisted
balance
}
}
```
**Parameter Mapping (Placeholders)**
* `$address`: Replaced with the user's wallet address as a hexadecimal string with the `0x` prefix, e.g., **`0x95ad73...`**.
* `$socialId`: Used when user information is not an address (email or Telegram ID) and replaced with the respective information.
For addresses encoded in case-insensitive formats (EVM or Aptos address starting with `0x`), Galxe converts them to lowercase before sending to your endpoint.
***
### **Response Requirements**
The body returned by `GraphQL` is in `JSON` format by default, compliant with Galxe's standards.
Galxe requires requests to respond within 5 seconds; otherwise, the request will be canceled.
***
### **Expression**
**Function Requirements**
1. Write an anonymous `JavaScript (ES6)` function with the type signature `(object) => int`.
2. The function takes the entire response object `resp` as a parameter.
3. It must return the number `1` or `0`, indicating whether the address qualifies for the credential.
Do not return Boolean values (`true/false`) or strings (`"0"/"1"`).
**Anonymous Function Format**
The function must be `anonymous`, with the first line written in the following format:
```javascript theme={null}
function(resp) {
/* Function body */
}
```
### **Security and Authorization**
When configuring the `GraphQL`, you can achieve secure access through request headers (such as `API KEY` or `tokens`). This information will not be exposed by Galxe, and only users with Space admin privileges can view it.
You should still be careful not to embed other private information in the expression encoding, as this will be made public.
### **CORS**
Galxe's API calls are not made through the browser but via backend servers. Although this avoids triggering browser CORS restrictions, we still send preflight `OPTIONS` requests during API configuration to validate the API's correctness.
For more information, visit [CORS Check](/quest/credential-api/overview/cross-domain-check).
# Multi Dimensional Config
Source: https://docs.galxe.com/quest/credential-api/graphql-cred/multi-config
Learn how to configure GraphQL Multi-Dimensional Credential
## Overview
GraphQL Multi-Dimensional Credential allows you to fetch user data via GraphQL APIs and validate eligibility across multiple dimensions. used to retrieve data for the extent of user participation.
If you want to understand the workflow and considerations of GraphQL credentials, please refer to the [introduction](/quest/credential-api/graphql-cred/introduction)
***
## Config process
### 1. Finding the Config in Task Settings
The option to configure GraphQL credential can be found in step 3, `Task Settings` of quest creation on the Galxe Dashboard, under the `Import Your Own Data` task type.
### 2. Basic Config
* **ID Type**
`ID Type` provides various identity options, including social accounts, blockchain addresses, and other unique identifiers.
* **Title**
Give your credential an enticing title.
* **Credential Source**
Choose `GraphQL` type
* **Type**
Choose `Multi Dimension`
### 3. Specify Dimensions
In Multi-Dimensional Credential configuration, you need to define specific dimensions to ensure each dimension is clearly identified and usable.
* **Identifier**:
* Enter a unique identifier for the dimension, e.g., `mainnet_eth_balance`.
* The identifier is used for internal calls and logic operations, and it must be globally unique.
* **Display Name**:
* Enter a display name for the dimension, e.g., `ETH balance on Mainnet`.
* This name will be displayed in the UI for user understanding.
* **Type**:
* Select the dimension type `COUNTER` from the dropdown menu.
* **Description**:
* Enter a description to explain the purpose of the dimension, e.g., "This dimension tracks the ETH balance of a user on Mainnet".
* The description must be within 256 characters.
### 4. Configure API
* Input Endpoint Example:
```plaintext theme={null}
https://api.example.com/query
```
* Add Headers (Optional)
```json theme={null}
`access-token`: `YOUR_TOKEN`
```
* Input Query:
```graphql theme={null}
query info($address: String!) {
tokenBalance(address: $address) {
balance
}
}
```
### 5. Test API Response
* **Input a test address and send the request to confirm the response**:
```json theme={null}
{
"balance": 100
}
```
### 6. Write Expressions
* **Token Balance Output**:
```javascript theme={null}
function(resp) {
return {
"mainnet_eth_balance": resp.balance
};
}
```
### 7. Description
Description of the certificate, supports rich text input, maximum 200 characters.
### 8. Call-to-Action Link
Guide users to specific operation pages to complete interactive tasks.
### 9. Participation End Time && Update Frequency (Optional)
* **Participation End Time**:
Control the time range of the credential, prohibiting new validations after the deadline.
* **Update Frequency**:
Remind users of the frequency of API data source updates, such as once a day or once every two days.
### 10. Config Rule
Configure rules in Quest to determine whether users meet the criteria.
* **Threshold Evaluation**:
When a certain threshold condition is met (e.g., >0), assign a fixed points directly.
* **Multiple Entries(Optional)**:
Enable users to claim rewards repeatedly once certain credentials are fulfilled, for example, a user earns 10 points for each 1 ETH they hold. If the user holds 5 ETH, they will earn 50 points.
***
## Example
### Galxe MSU Space points balance
* **Specify Dimensions**
Identifier:`points_balance`
Display Name:`points balance on msu`
Type:`COUNTER`
Description:`The balance of points you hold on msu`
* **Endpoint**
```plaintext theme={null}
https://graphigo-business.prd.galaxy.eco/query
```
* **Headers**
`No header`
* **Query**
```graphql theme={null}
query info($address: String!) {
space(id: 68267) {
addressLoyaltyPoints(address: $address) {
points
}
}
}
```
* **Response**
```json theme={null}
{
"space": {
"addressLoyaltyPoints": {
"points": 100
}
}
}
```
* **Expression**
```javascript theme={null}
function(resp) {
try {
let points = BigInt(resp.space.addressLoyaltyPoints.points);
return { "points_balance": points };
} catch (error) {
return { "points_balance": 0 };
}
}
```
# Single Dimensional Config
Source: https://docs.galxe.com/quest/credential-api/graphql-cred/single-config
Learn how to configure GraphQL Single-Dimensional Credential
## Overview
GraphQL Single-Dimensional Credential allows you to fetch user data via GraphQL APIs and validate user eligibility based on a single condition. It is suitable for when task verification is equivalent to answering the question, *Did this particular user perform this task — yes or no?*
If you want to understand the workflow and considerations of GraphQL credentials, please refer to the [introduction](/quest/credential-api/graphql-cred/introduction)
## Config process
### 1. Finding the Config in Task Settings
The option to configure GraphQL credential can be found in step 3, `Task Settings` of quest creation on the Galxe Dashboard, under the `Import Your Own Data` task type.
### 2. Basic Config
* **ID Type**
`ID Type` provides various identity options, including social accounts, blockchain addresses, and other unique identifiers.
* **Title**
Give your credential an enticing title.
* **Credential Source**
Choose `GraphQL` type
* **Type**:
Choose `Single Dimension`
### 3. Configure API
* Input Endpoint Example:
```plaintext theme={null}
https://api.example.com/query
```
* Add Headers (Optional)
```json theme={null}
`access-token`: `YOUR_TOKEN`
```
* Input Query:
```graphql theme={null}
query info($address: String!) {
tokenBalance(address: $address) {
balance
}
}
```
### 4. Test API Response
* Input a test address, send the request, and confirm whether the response is correct.
* The response must be in JSON format. Example:
```json theme={null}
{
"balance":100
}
```
### 5. Write Expressions
1. **Points balance validation**:
```javascript theme={null}
function(resp) {
return resp.balance >= 100 ? 1 : 0;
}
```
### 6. Description
Description of the certificate, supports rich text input, maximum 200 characters.
### 7. Call-to-Action Link
Guide users to specific operation pages to complete interactive tasks.
### 8. Participation End Time && Update Frequency (Optional)
* **Participation End Time**:
Control the time range of the credential, prohibiting new validations after the deadline.
* **Update Frequency**:
Remind users of the frequency of API data source updates, such as once a day or once every two days.
***
## Example
### Galxe MSU Space requires holding at least 100 points
* **Endpoint**
```plaintext theme={null}
https://graphigo-business.prd.galaxy.eco/query
```
* **Headers**
`No header`
* **Query**
```graphql theme={null}
query info($address: String!) {
space(id: 68267) {
addressLoyaltyPoints(address: $address) {
points
}
}
}
```
* **Response**
```json theme={null}
{
"space": {
"addressLoyaltyPoints": {
"points": 100
}
}
}
```
* **Expression**
```javascript theme={null}
function(resp) {
return resp.space.addressLoyaltyPoints >= 100 ? 1 : 0;
}
```
# CORS Check
Source: https://docs.galxe.com/quest/credential-api/overview/cross-domain-check
The Galxe platform uses a Cross-Origin Resource Sharing (CORS) check mechanism to ensure that the target API explicitly authorizes calls from the Galxe backend. The role of CORS is to verify whether the API accepts cross-origin requests, ensuring the legality and security of interactions. The target API can authorize access for Galxe by specifying the source or using a wildcard (*).
## Why Does Galxe Need Cross-Domain Checks?
### **1. Ensure Target API Authorization**
When Galxe calls third-party APIs from the backend, it is necessary to confirm whether these APIs have open access permissions. The CORS configuration authorizes access by returning the `Access-Control-Allow-Origin` header:
**Designated Source**: Such as [`https://dashboard.galxe.com`.](https://dashboard.galxe.com.)
**Wildcard (`*`)**: Allows all sources, including Galxe.
### **2. Prevent Unauthorized Calls**
CORS checks can prevent:
**Data Breach**: Prevent unauthorized sources from accessing the API.
**Abuse of Functionality**: Restrict the scope of API calls.
## The Working Mechanism of CORS
### **1. Access-Control-Allow-Origin**
The target API can be authorized in two ways:
**Designated Source**: More stringent configuration, allowing requests only from Galxe.
```http theme={null}
access-control-allow-origin: https://dashboard.galxe.com
```
* **Wildcard (\*)**: Allows cross-origin requests from all sources and meets authorization requirements.
```http theme={null}
access-Control-Allow-Origin: *
```
### **2. Access-Control-Allow-Methods**
Specify the allowed HTTP methods, for example:
```http theme={null}
access-control-allow-methods: GET, POST,OPTIONS
```
### **3. Preflight Request**
Galxe requires that the target API supports OPTIONS requests to verify that the CORS configuration is correct.
## Server Configuration Requirements
### **1. Example Configuration**
The target API needs to support the following CORS configuration:
Open Authorization:
```http theme={null}
access-control-allow-origin: *
access-control-allow-methods: GET, POST,OPTIONS
```
Designated Source Authorization:
```http theme={null}
access-control-allow-origin: https://dashboard.galxe.com
access-control-allow-methods: GET, POST,OPTIONS
```
### **2. Response to Preflight Request**
The target server must appropriately respond to preflight requests:
```http theme={null}
HTTP/1.1 204 No Content
access-control-allow-origin: *
access-control-allow-methods: GET, POST,OPTIONS
```
## Testing and Verification
Recommended to Use curl Command
```base theme={null}
// For GET
curl --head -X 'OPTIONS' -H 'Access-Control-Request-Headers: Content-Type' -H 'Access-Control-Request-Method: GET' -H 'Origin: https://dashboard.galxe.com' '$END_POINT_URL_WITHOUT_ADDRESS_REPLACED$'
// For POST
curl --head -X 'OPTIONS' -H 'Access-Control-Request-Headers: Content-Type' -H 'Access-Control-Request-Method: POST' -H 'Origin: https://dashboard.galxe.com' '$YOUR_URL_HERE$'
```
Correct Response Example
```http theme={null}
HTTP/1.1 204 No Content
access-control-allow-origin: https://dashboard.galxe.com
access-control-allow-methods: POST,GET,OPTIONS
```
## Frequently Asked Questions
### 1. Why Is Access-Control-Allow-Origin: \* Allowed?
Because Galxe’s check only verifies whether the target API supports cross-origin, \* indicates that all origins are authorized, including Galxe, which meets the requirements.
### 2. Why Did the Test Succeed but the Save Fail?
The target API may not be handling preflight requests correctly. Ensure that OPTIONS requests are supported and that a complete CORS configuration is returned.
# Introduction
Source: https://docs.galxe.com/quest/credential-api/overview/introduction
### **Note for non-developers**
The following documentation is intended to assist developers to understand and set up advanced credentials (tasks) to be used on Galxe Quest. For non-developers, the following resources may be more informative for setting up onchain tasks on Galxe Quest.
1. [Help Center article describing task types available on Galxe Quest](https://help.galxe.com/en/articles/9728885-create-quest-tasks-settings)
2. [Galxe Onchain Task Overview (YouTube)](https://www.youtube.com/watch?v=PkJJ8cRCvc8)
3. [Mastering Onchain Tasks on Galxe Quest (Course)](https://bulletlabs.notion.site/Mastering-Onchain-Tasks-on-Galxe-Quest-1361204ce01180b8a4a7cfc048085b4f)
### Types of Advanced Credential Configurations
Galxe offers a variety of **Advanced Credential Configuration Types**, allowing you to verify user-specific information or onchain tasks in a Galxe Quest. These configuration types can be used for setting onchain tasks:
| **Type** | **Features** |
| ------------------ | -------------------------------------------------------------------------------------------------------- |
| **CSV File** | Easy to use, suitable for small-scale data validation, requires manual upload. |
| **Google Sheets** | Periodic synchronization, easy to manage, relies on Google services. |
| **API** | Supports real-time data push to Galxe. |
| **REST** | Supports dynamic updates, ideal for developers needing complex data structures and real-time validation. |
| **GraphQL** | Provides flexible querying capabilities, suitable for complex interaction scenarios. |
| **Contract Query** | Enables contract query capabilities, commonly used to query `ERC20` or `ERC721` holders. |
# Introduction
Source: https://docs.galxe.com/quest/credential-api/rest-cred/introduction
`REST` Credentials support integration with any available `REST` endpoints and send requests during user verification for interaction.
The `REST` Credential is a method used by Galxe to pull data from your `RESTful HTTPS` backend (or any legally accessible `HTTP RESTful` endpoint). It takes a single wallet address as input and outputs `1` (eligible) or `0` (not eligible) to determine whether the wallet address qualifies.
***
### **Workflow**
1. **app.galxe.com**: When a user clicks "Verify" on a Quest page, Galxe sends the user's wallet address, social media information, or other selected **id type** as an input parameter.
2. **Galxe Backend**: Based on the pre-configuration, Galxe sends an HTTP request and query containing the wallet address to your `REST API` and waits for the response.
3. **Your Backend**: After receiving the HTTP request from Galxe, your backend processes the request and returns the response data related to the wallet address.
4. **Galxe Backend**: Processes the `response.body` from your backend using predefined expressions to determine if the user meets the conditions.
`35.185.209.0` and `35.203.155.18` are our outbound IPs. Failure to whitelist these may result in 403 errors when accessing the service.
***
### **Configuration Requirements**
*What is required for setting up a task using a REST credential.*
**API Specification**
* **Endpoint**:
The URL of the `REST` endpoint.
We only support the default ports for HTTP and HTTPS (80 and 443).
* **(Optional) Headers**:
`Key-value` pairs included in the `REST` request.
**Parameter Mapping (Placeholders)**
* `$address`: Replaced with the user's wallet address as a hexadecimal string with the `0x` prefix, e.g., **`0x95ad73...`**.
* `$addressWithout0x`: Replaced with the user's wallet address as a hexadecimal string without the `0x` prefix, e.g., **`95ad73...`**, typically used for constructing **`eth_call`** requests.
* `$socialId`: Used when user information is not an address (email or Telegram ID) and replaced with the respective information.
For addresses encoded in case-insensitive formats (EVM or Aptos addresses starting with `0x`), Galxe converts them to lowercase before sending to your endpoint.
***
### **Data Format**
Galxe supports **JSON body format** exclusively for both `GET` and `POST` responses.
```json theme={null}
{
"key": "value"
}
```
Galxe requires requests to respond within 5 seconds; otherwise, the request will be canceled.
***
### **Expression**
**Function Requirements**
1. Write an anonymous `JavaScript (ES6)` function with the type signature `(object) => int`.
2. The function takes the entire response object `resp` as a parameter.
3. It must return the number `1` or `0`, indicating whether the address qualifies for the credential.
Do not return Boolean values (`true/false`) or strings (`"0"/"1"`).
**Anonymous Function Format**
The function must be `anonymous`, with the first line written in the following format:
```javascript theme={null}
function(resp) {
/* Function body */
}
```
To ensure a more secure `function`, always validate the structure of the `resp` object before accessing its properties,
this helps prevent errors or unexpected behavior when the API response is incomplete or incorrectly formatted.
### **Security and Authorization**
When configuring the `REST API`, you can achieve secure access through request headers (such as `API KEY` or `tokens`). This information will not be exposed by Galxe, and only users with Space admin privileges can view it.
You should still be careful not to embed other private information in the expression encoding, as this will be made public.
### **CORS**
Galxe's API calls are not made through the browser but via backend servers. Although this avoids triggering browser CORS restrictions, we still send preflight `OPTIONS` requests during API configuration to validate the API's correctness. This process does not adhere to the [Simple Request Convention](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests).
For more information, visit [CORS Check](/quest/credential-api/overview/cross-domain-check).
# Multi Dimensional Config
Source: https://docs.galxe.com/quest/credential-api/rest-cred/multi-config
Learn how to configure REST Multi-Dimensional Credential
## Overview
REST Multi-Dimensional Credential allows you to fetch user data via RESTful APIs and validate eligibility across multiple dimensions. used to retrieve data for the extent of user participation. It is suitable when the verification for tasks is equivalent to answering the question, *How much, how often, or how many times did a user perform the task?*
If you want to understand the workflow and considerations of REST credentials, please refer to the [introduction](/quest/credential-api/rest-cred/introduction)
***
## Config process
### 1. Finding the Config in Task Settings
The option to configure API credential can be found in step 3, `Task Settings` of quest creation on the Galxe Dashboard, under the `Import Your Own Data` task type.
### 2. Basic Config
* **ID Type**
`ID Type` provides various identity options, including social accounts, blockchain addresses, and other unique identifiers.
* **Title**
Give your credential descriptive title matching the task at hand.
* **Credential Source**
Choose `REST` type and select `GET` or `POST` based on your API request type.
* **Type**
Choose `Multi Dimension`
### 3. Specify Dimensions
In Multi-Dimensional Credential configuration, you need to define specific dimensions to ensure each dimension is clearly identified and usable.
* **Identifier**:
* Enter a unique identifier for the dimension, e.g., `mainnet_eth_balance`.
* The identifier is used for internal calls and logic operations, and it must be globally unique.
* **Display Name**:
* Enter a display name for the dimension, e.g., `ETH balance on Mainnet`.
* This name will be displayed in the UI for user understanding.
* **Type**:
* Select the dimension type `COUNTER` from the dropdown menu.
* **Description**:
* Enter a description to explain the purpose of the dimension, e.g., "This dimension tracks the ETH balance of a user on Mainnet".
* The description must be within 256 characters.
### 4. Configure API
* **Input Endpoint**:
GET Request Example:
```plaintext theme={null}
https://api.example.com/check-user?wallet=$address
```
POST Request Example:
```plaintext theme={null}
https://api.example.com/check-user
```
* **Add Headers (Optional)**:
```json theme={null}
`Authorization`: `Bearer YOUR_API_KEY`
```
* **Input Body (For POST Requests Only)**:
```json theme={null}
{
"check_user_address": "$address"
}
```
### 5. Test API Response
* **Input a test address and send the request to confirm the response**:
```json theme={null}
{
"isWhitelisted": true,
"balance": 1000
}
```
### 6. Write Expressions
* **Token Balance Output**:
```javascript theme={null}
function(resp) {
return {
"mainnet_eth_balance": resp.balance
};
}
```
### 7. Description
Description of the certificate, supports rich text input, maximum 200 characters.
### 8. Call-to-Action Link
Guide users to specific operation pages to complete interactive tasks.
### 9. Participation End Time && Update Frequency (Optional)
* **Participation End Time**:
Control the time range of the credential, prohibiting new validations after the deadline.
* **Update Frequency**:
Remind users of the frequency of API data source updates, such as once a day or once every two days.
### 10. Config Rule
Configure rules in Quest to determine whether users meet the criteria.
* **Threshold Evaluation**:
When a certain threshold condition is met (e.g., >0), assign a fixed points directly.
* **Multiple Entries(Optional)**:
Enable users to claim rewards repeatedly once certain credentials are fulfilled, for example, a user earns 10 points for each 1 ETH they hold. If the user holds 5 ETH, they will earn 50 points.
***
## Example
### ETH Balance Amount
* **Specify Dimensions**
Identifier:`mainnet_eth_balance`
Display Name:`ETH balance on Mainnet`
Type:`COUNTER`
Description:`The amount of ETH you hold on mainnet`
* **Endpoint**
```plaintext theme={null}
https://mainnet.infura.io/v3/YOUR-API-KEY
```
* **Request Type**
`POST`
* **Headers**
`No header`
* **Body**
```json theme={null}
{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": [
"$address",
"latest"
],
"id": 1
}
```
* **Response**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x7c2562030800"
}
```
* **Expression**
```javascript theme={null}
function(resp) {
try {
let balance = BigInt(resp.result);
return { "mainnet_eth_balance": balance };
} catch (error) {
return { "mainnet_eth_balance": 0 };
}
}
```
# Single Dimensional Config
Source: https://docs.galxe.com/quest/credential-api/rest-cred/single-config
Learn how to configure REST Single-Dimensional Credential
## Overview
REST Single-Dimensional Credential allows you to fetch user data via RESTful APIs and validate user eligibility based on a single condition. It is suitable for when task verification is equivalent to answering the question, *Did this particular user perform this task -- yes or no?*
If you want to understand the workflow and considerations of REST credentials, please refer to the [introduction](/quest/credential-api/rest-cred/introduction)
***
## Config process
### 1. Finding the Config in Task Settings
The option to configure REST credential can be found in step 3, [Task Settings](https://help.galxe.com/en/articles/9728885-create-quest-tasks-settings) of quest creation on the Galxe Dashboard, under the `Import Your Own Data` task type.
### 2. Basic Config
* **ID Type**
`ID Type` provides various identity options, including social accounts, blockchain addresses, and other unique identifiers.
* **Title**
Give your credential a descriptive title relevant to the task at hand.
* **Credential Source**
Choose `REST` type and select `GET` or `POST` based on your API request type.
* **Type**
Choose `Single Dimension`.
### 3. Configure API
* Input Endpoint URL
GET Request Example:
```plaintext theme={null}
https://api.example.com/check-user?wallet=$address
```
POST Request Example:
```plaintext theme={null}
https://api.example.com/check-user
```
* Add Headers (Optional)
```json theme={null}
`Authorization`: `Bearer YOUR_API_KEY`
```
* Input Body (For POST Requests Only):
```json theme={null}
{
"check_user_address": "$address"
}
```
### 4. Test API Response
* Input a test address, send the request, and confirm whether the response is correct.
* The response must be in JSON format. Example:
```json theme={null}
{
"isWhitelisted": true,
"balance": 1000
}
```
### 5. Write Expressions
1. **Whitelist Validation**:
```javascript theme={null}
function(resp) {
return resp.isWhitelisted ? 1 : 0;
}
```
1. **Token Balance Validation**:
```javascript theme={null}
function(resp) {
return resp.balance >= 1000 ? 1 : 0;
}
```
1. **Combined Condition Validation**:
```javascript theme={null}
function(resp) {
return resp.isWhitelisted && resp.balance >= 500 ? 1 : 0;
}
```
### 6. Description
Description of the certificate, supports rich text input, maximum 200 characters.
### 7. Call-to-Action Link
Guide users to specific operation pages to complete interactive tasks.
### 8. Participation End Time & Update Frequency (Optional)
* **Participation End Time**:
Control the time range of the credential, prohibiting new validations after the deadline.
* **Update Frequency**:
Remind users of the frequency of API data source updates, such as once a day or once every two days.
***
## Example
### Polygon OAT Holder
* **Endpoint**
```plaintext theme={null}
https://api.covalenthq.com/v1/matic-mainnet/address/$address/collection/0x5D666F215a85B87Cb042D59662A7ecd2C8Cc44e6/
```
* **Request Type**
`GET`
* **Headers**
```json theme={null}
Authorization: Bearer YOU_API_KEY
```
* **Response**
```plaintext theme={null}
{
"data": {
"updated_at": "2023-06-26T05:12:35.553904397Z",
"address": "0x123",
"collection": "0x5d666f215a85b87cb042d59662a7ecd2c8cc44e6",
"is_spam": false,
"items": []
},
"error": false,
"error_message": null,
"error_code": null
}
```
* **Expression**
```javascript theme={null}
function(resp) {
if (resp.data.items != null && resp.data.items.length > 0) {
return 1
}
return 0
}
```
### ETH Balance Holder
* **Endpoint**
```plaintext theme={null}
https://mainnet.infura.io/v3/YOUR-API-KEY
```
* **Request Type**
`POST`
* **Headers**
`No header`
* **Body**
```json theme={null}
{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": [
"$address",
"latest"
],
"id": 1
}
```
* **Response**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x7c2562030800"
}
```
* **Expression**
```javascript theme={null}
function(resp) {
if (BigInt(resp.result) > 0) {
return 1
}
return 0
}
```
### General NFT Holder
* **Endpoint**
```plaintext theme={null}
https://mainnet.infura.io/v3/YOUR-API-KEY
```
* **Request Type**
`POST`
* **Headers**
`No header`
* **Body**
```json theme={null}
{
"jsonrpc":"2.0",
"id":1,
"method":"eth_call",
"params":[
{
"data":"0x70a08231000000000000000000000000$addressWithout0x",
"to":"0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB"
},
"latest"
]
}
```
* **Response**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x00000000000000000000000000000001"
}
```
* **Expression**
```javascript theme={null}
function(resp) {
if (BigInt(resp.result) > 0) {
return 1
}
return 0
}
```
# What is Galxe Quest
Source: https://docs.galxe.com/quest/introduction
Galxe Quest is the #1 platform for building and engaging with web3 communities, trusted by the most significant and reputable brands in the space. Through a turnkey, no-code solution, Quest connects projects and applications with millions of users through reward-based loyalty programs.
Trusted by industry leaders like Optimism, Arbitrum, and Polygon, Galxe is your gateway to web3’s largest onchain distribution platform with over 22 million users. Galxe Quest is well known as the largest web3 community building platform.
# Key Features
**Automated Precision in User Growth**: Take your marketing and growth ambitions to new heights with our automated solutions, leveraging both on-chain analytics and off-chain interactions for unmatched precision.
**Streamlined User Onboarding**: Transform newcomers into knowledgeable users with our engaging Learn-to-Experience-to-Earn campaigns, featuring quizzes, insightful readings, and interactive on-chain quests designed to streamline the user onboarding process.
**Authentic Community Engagement**: Cultivate a genuine community experience by safeguarding your ecosystem from bots with our sybil-resistant credentials, ensuring a human-centric web3 growth path.
**Amplified Brand Visibility**: Propel your brand into the spotlight by leveraging Galxe's expansive reach through strategic social media integrations, ensuring your presence resonates across the digital landscape.
**Discovering True Loyalty**: Pinpoint and connect with your most passionate supporters by utilizing specific credentials to identify and engage loyal users within and beyond your community boundaries.
**Sustained User Engagement**: Foster lasting relationships with your audience by initiating a comprehensive loyalty program, powered by continuous campaigns and rewarding incentives that drive long-term user retention.
# Smart Contract Audits
Source: https://docs.galxe.com/quest/smart-contract/audit
The core contracts found in [galxe-contracts](https://github.com/Galxe/galxe-contracts) repository have been audited by multiple independent third-party firms. You can download their audit reports below:
| Audit | Date | Link |
| -------- | ---------- | -------------------------------------------------------------------------------------------- |
| SlowMist | June 2022 | [download](https://github.com/Galxe/docs/raw/main/files/audit-slowmist-gas-optimization.pdf) |
| SlowMist | March 2022 | [download](https://github.com/Galxe/docs/raw/main/files/audit-slowmist.pdf) |
| Certik | June 2021 | [download](https://github.com/Galxe/docs/raw/main/files/audit-certik.pdf) |
# SpaceStation
Source: https://docs.galxe.com/quest/smart-contract/contracts/spacestation
## Contract Address:[](#contract-address "Direct link to heading")
> This is an incomplete list of our contract addresses
| Chain | Address |
| --------- | ------------------------------------------ |
| Polygon | 0xf6D1B85af155229AcD7B523601148585A1ff67C6 |
| BNB Chain | 0x2D18f2d27D50C9b4013DEBA3D54f60996bD8847E |
| Ethereum | 0x75cdA57917E9F73705dc8BCF8A6B2f99AdBdc5a5 |
| Avalanche | 0x13D8c4e3741e968Cc8E740bdB02537cB1d2d70e6 |
| Arbitrum | 0x9e6eF7F75ad88D4Edb4C9925C94B769C5b0d6281 |
| Fantom | 0x168a6136fD4F60699B64fb9F8a2F8ed95B279954 |
| Moonbeam | 0xa36AABC82b62b01884a66Dd9f51aB2E7061748aA |
| IoTex | 0xc24785Ed62B06Bf4b9B304b8153969ABe39fF7BC |
| Optimism | 0x2e42f214467f647Fe687Fd9a2bf3BAdDFA737465 |
Sample transaction:
[https://etherscan.io/tx/0xac053601cffb0411a7095bc4e811492ab1ebc1e47fc17b622d898bf5b2da15ae](https://etherscan.io/tx/0xac053601cffb0411a7095bc4e811492ab1ebc1e47fc17b622d898bf5b2da15ae)
[https://polygonscan.com/tx/0x74aed47b6cb146d643ac07722029dbd228c995aa6dab69a19d2f22fccaf40b47](https://polygonscan.com/tx/0x74aed47b6cb146d643ac07722029dbd228c995aa6dab69a19d2f22fccaf40b47)
[https://bscscan.com/tx/0x29c88c719d1a16db784aca9b0ef33970239aba0d4dec03bbb7b126afa8a55f7d](https://bscscan.com/tx/0x29c88c719d1a16db784aca9b0ef33970239aba0d4dec03bbb7b126afa8a55f7d)
## Legacy SpaceStation Contracts[](#legacy-spacestation "Direct link to heading")
These contracts may still be in use
| Chain | Address |
| --------- | ------------------------------------------ |
| Arbitrum | 0xA0D893e6F4bb0e5823c995310BF1B1B4387ac83D |
| Arbitrum | 0x1ae981A0a3AE5F9cDc059d9478D2C37E8eB442eB |
| Avalanche | 0xe338D00f5fBD32Fa414531be1685418c7C118E83 |
| BNB Chain | 0x835f22b4280aAf357d12DBf03721651b3A8b0167 |
| BNB Chain | 0x5C1274456be4dd280429B9A8319e552cAD2595fA |
| BNB Chain | 0x760B8237e457e6A2b5b196ae073EF0301b8316a2 |
| Ethereum | 0xc92EDE6aC9865111356B8f51fBD7ee8D261D9637 |
| Ethereum | 0x5bD25d2f4f26Bc82A34dE016D34612A28A0Cd492 |
| Ethereum | 0x987fb80B5E8646A2DC4C276881484BD442d645F3 |
| Ethereum | 0xaae9f9d4fb8748feba405cE25856DC57C91BbB92 |
| Fantom | 0x597e0A675D071228edFC8918f54A5d5257bD6663 |
| Fantom | 0x88a8378d0f3d4ff110d2757e12fe3adb17903403 |
| Polygon | 0xdeb1F826c512EEE2FA9398225A3401A0Dd5311E2 |
| Polygon | 0x6e7801d5b07dA1A82F6D1930685731a50645B182 |
| Polygon | 0x44D2a93948B70DC0568020AaD2efc6FE7d146404 |
| Polygon | 0x6cad6e1abc83068ea98924aef37e996ed02abf1c |
# StarNFT
Source: https://docs.galxe.com/quest/smart-contract/contracts/starnft
> This page is still in progress
Sample transaction:
[https://etherscan.io/tx/0xac053601cffb0411a7095bc4e811492ab1ebc1e47fc17b622d898bf5b2da15ae](https://etherscan.io/tx/0xac053601cffb0411a7095bc4e811492ab1ebc1e47fc17b622d898bf5b2da15ae)
[https://polygonscan.com/tx/0x74aed47b6cb146d643ac07722029dbd228c995aa6dab69a19d2f22fccaf40b47](https://polygonscan.com/tx/0x74aed47b6cb146d643ac07722029dbd228c995aa6dab69a19d2f22fccaf40b47)
[https://bscscan.com/tx/0x29c88c719d1a16db784aca9b0ef33970239aba0d4dec03bbb7b126afa8a55f7d](https://bscscan.com/tx/0x29c88c719d1a16db784aca9b0ef33970239aba0d4dec03bbb7b126afa8a55f7d)
# Introduction
Source: https://docs.galxe.com/quest/smart-contract/introduction
Contract repo: [https://github.com/Galxe/galxe-contracts](https://github.com/Galxe/galxe-contracts)
Contract technical specifications: [https://github.com/Galxe/galxe-contracts/blob/main/SPECIFICATION.md](https://github.com/Galxe/galxe-contracts/blob/main/SPECIFICATION.md)