How to Build Digital Credentials using Solana Attestation Service
16 min readUpdated Feb 8, 2026
TL;DR
Learn how to build digital credentials using Solana Attestation Service, a new feature in Solana that allows you to create and verify digital credentials. It focuses on Solana, Attestation, Web3, and TypeScript so you can understand the main ideas, trade-offs, and practical context before reading the full article.
The Solana Attestation Service (SAS) is a powerful on-chain credentialing system that enables developers to create, manage, and verify digital attestations on the Solana blockchain. Think of it as a decentralized way to issue and verify credentials, certificates, badges, or any form of digital proof that someone or something meets certain criteria.
SAS introduces powerful capabilities for associating offchain data with on-chain accounts, building trust and identity systems, including:
Compliance Systems - Provable KYC/AML status
Professional Credentials - Verification of professional certificates or degrees
Gaming Achievements - Issuance of badges/milestone recognition
Event Attendance - Proof of participation
Loyalty - Rewards users for engagement, volume, etc.
Attestations can then be consumed by service providers (e.g., DEXs, DAOs, or other platforms) to vet users and gate services based on their credentials (e.g., enable VIP Members to access unique content on a website or Accredited Investors to participate in certain on-chain investment opportunities).
This guide will walk you through creating a complete attestation script that:
Creates a new credential with authorized signers
Defines a schema for the type of data we want to attest
Issues an attestation to a specific user
Updates authorized signers for enhanced security
Verifies attestations for both attested and non-attested users
Closes an attestation (effectively revoking a user's credential)
The end goal will be to see a working attestation system in action:
Starting Solana Attestation Service Demo1. Setting up wallets and funding payer... - Airdrop completed: 384wkVUZsyuk53Npyy5N29tWTRA6dGe82b6fpBa4gKMDHoZYsb3iNAUfYMD6Lo2V3MYJeDhk8xvEDrmyxjeW2xdB2. Creating Credential... - Credential created - Signature: 5LnkP762S9yvcLxFUVU7N3Mzen5Tqp8abC4h1rJYZn1vCviq7GpyFvUNVneVd8btiV7KK6pe5NEpXvwtTXK96gM1 - Credential PDA: 3yB9Xrgg73oWxuQv8564q9LwwRL2rX2fjZD7ssy3X4M33. Creating Schema... - Schema created - Signature: 4qHfY6FfjsUrssymRDWgShgr2sxRgWTbSdHxnJhgus7Cra5t6n6f4snhPDDkMyAX9bkqpD7aMCbKUpoJnD9NXzoS - Schema PDA: FfNqeLfPHy4p7FPgH2LDTm9gzVWSDcupA3LUhiMEzBXw4. Creating Attestation... - Attestation created - Signature: 3czDWMmDkZEJbww7qfphcKe96vJJMAawFk2DedbknrzVpBSJ5fGBjtEK1aZHsYzvj8QLvRcadohEaxANNb4c4nUN - Attestation PDA: 6JEEL89jNXvxk63N6ND8njsp6e1Ve8BLZYShYNfjFajR5. Updating Authorized Signers... - Authorized signers updated - Signature: 23V3bmTYnKUA6fT9WnchFmKi7bNj9biqxxnLBW9coUtkWhippu49PrY5fnefAcHWKofNDoojCicD2qJFq16RNz1Y6. Verifying Attestations... - Attestation data: { name: 'test-user', age: 100, country: 'usa' } - Test User is verified - Random User is not verified7. Closing Attestation... - Closed attestation - Signature: 5DS7GYpzKirWcusEgBhN3LGfX7D34q5rSQmbdNpCmzU5nYM1CUA4fJ3B9DRXwuiYNHvMnbBRSiMGDVJoCfLMc6tiSolana Attestation Service demo completed successfully!
The attestation system consists of three main components:
Credentials - The top-level identity or organization that issues attestations. Think of this as a "university" that issues diplomas or the "company" that issues employee badges.
Schemas - Define the structure and fields of data that can be attested. Schemas are essentially a template that specifies what information (name, age, skills, etc.) will be included in attestations.
Attestations - Individual claims made about specific entities following a particular schema. These are the actual "diplomas" or "badges" issued to users.
Data Privacy - Because attestations are on-chain, the data can be read by anyone. Do not store personal identifiable or other sensitive information directly on chain. Consider what data to include directly vs. storing hashes of sensitive information off-chain.
Trusted Credentials - anyone can create a credential/schema. Make sure you know/trust the credential provider if you are accepting an Attestation as verification of a user's credentials.
User Verification - ensure connected wallets are actual users by requiring signing a message (e.g., Sign in with Solana or Supabase)
Versioning - Note that Schemas are versioned, so you will need to establish business practices for monitoring and handling schema changes. This guide will walk you through using a single version–we will cover more advanced applications in a future guide.
Performance - Verification checks can be batched and cached. For certain use cases, consider indexing services for applications that need to check many attestations frequently.
Before moving on, let's examine the Schema Layout and Fields we defined above. The SCHEMA_LAYOUT array defines the data types for each field in our attestation, where each number corresponds to a specific data type from the Solana Attestation Service's type system. In our example, Buffer.from([12, 0, 12]) maps to our three fields:
the first 12 represents a String type for the "name" field,
0 represents a U8 integer type for the "age" field, and
the final 12 represents another String type for the "country" field.
The SCHEMA_FIELDS array provides human-readable names that correspond one-to-one with the layout types. This approach ensures that when attestations are created, the data is properly typed and validated according to the schema definition. The available data types range from basic integers (U8, U16, U32, U64, U128) and signed integers (I8-I128) to booleans, characters, strings, and even vectors of these types, giving you flexibility in designing your attestation data structures. Check out the full list of options and mapping here.
Now let's add a verification function that demonstrates how to check if a user has a valid attestation. To verify a user's attestation, we will need to pass two pieces of information: the user's address (or other identifier associated with the user) and the Schema address that you want to validate against. Add the verifyAttestation function to your code and then we will walk through how it works:
Now, let's build the main demonstration function that showcases the complete attestation workflow. Add the main function to your code -- we'll use this to outline for our steps:
The current code includes spaces for 7 steps. We've started by creating our client and calling our setupWallets function. Let's add the remaining steps next.
Here, we just need to use a couple of helper function sas-lib package:
deriveCredentialPda: derives the PDA of our credential account based on the authority (our issuer wallet) and the name of our credential (meaning an issuer could create multiple credentials by creating new ones with different names) (ref).
getCreateCredentialInstruction: will assemble the instruction to create the credential account (ref). For now, we will just add a single authorized signer, so that we can add our second signer later.
We send our instruction to the network by calling our sendAndConfirmInstructions helper function.
Next, we need to define our Schema to define the structure of data that can be attested (name, age, country in our example). Add the following to your code:
Next, we need to issue an actual attestation to a specific user with the defined data and expiration. Add the following to Step 4 of your main function:
Like before, we will first derive our Attestation PDA using a helper function, deriveAttestationPda (ref). Note that the parameters include a nonce which can be a user's address or some other unique identifier address (e.g. some value stored off-chain).
Prior to calling getCreateAttestationInstruction, we need to do a couple of things:
We must fetch our Schema from the chain -- we will use fetchSchema to get the deserialized schema data which is required to serialize our attestation data. We do so by passing the schema data and our attestation into serializeAttestationData.
We define an expiration of 1-year from now.
Notice that the authority in our instruction parameters is authorizedSigner1, the authorized signer we defined in Step 2 when we created our credential.
Finally, we send the instruction to the network to create the attestation PDA.
We mentioned earlier that we can update a credential's authorized signers. Let's add authorizedSigner2 as an authorized signer to our credential to demonstrate how to manage who can issue attestations for the credential. Add the following to Step 5 of your main function:
We just need to assemble an instruction passing our new signers array (this replaces the old list of signers, so make sure to include existing signers you wish to keep) into getChangeAuthorizedSignersInstruction and send it to the network with our helper function.
Let's run a verification check to show how you might check if users have valid attestations, testing both attested and non-attested users. Normally, you might run something like this on your backend when a user signs into your platform. Add the following to Step 6 of your main function:
// Step 6: Verify Attestationsconsole.log('\n6. Verifying Attestations...')const isUserVerified = await verifyAttestation({ client, schemaPda, userAddress: testUser.address,})console.log(` - Test User is ${isUserVerified ? 'verified' : 'not verified'}`)const randomUser = await generateKeyPairSigner()const isRandomVerified = await verifyAttestation({ client, schemaPda, userAddress: randomUser.address,})console.log(` - Random User is ${isRandomVerified ? 'verified' : 'not verified'}`)
Here, we are calling our helper function verifyAttestation twice: once with our testUser address (which we would expect to be verified at this point) and a new randomUser who does not have an attestation (we would expect this user's verification to fail).
In order to generate an attesation instruction, we need to get the Event Authority address using deriveEventAuthorityAddress. The event authority is used to emit close events in the SAS program. We then assemble our instruction using the getCloseAttestationInstruction -- note that we must pass one of our authorizedSigner addresses into the authority parameter.
Congratulations! You've successfully implemented a complete Solana Attestation Service system. You now have a working demonstration that shows how to:
Create credentials that represent issuing authorities
Define schemas for structured attestation data
Issue attestations to specific users
Manage authorized signers for enhanced security
Verify attestations programmatically
Close attestation as needed
The Solana Attestation Service provides a powerful foundation for building trust and identity systems on Solana. Whether you're creating compliance systems, financial credentials, professional certifications, or gaming achievements, SAS gives you the tools to issue and verify claims in a decentralized, transparent way.