attest.so
Version:
<div align="center">
258 lines (226 loc) • 8.8 kB
text/typescript
import * as anchor from '@coral-xyz/anchor'
import { Program, AnchorError } from '@coral-xyz/anchor'
import { Attest } from '../target/types/attest'
import { PublicKey, SystemProgram } from '@solana/web3.js'
import { expect } from './_expect'
// import { assert, expect } from 'chai'
const {
createMint,
createAccount,
mintTo,
getAssociatedTokenAddress,
} = require('@solana/spl-token')
import { TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID } from '@solana/spl-token'
describe('attest.so', () => {
const provider = anchor.AnchorProvider.env()
anchor.setProvider(provider)
const attest = anchor.workspace.Attest as Program<Attest>
const authorityKeypair = anchor.web3.Keypair.generate()
const unauthorityKeypair = anchor.web3.Keypair.generate()
const recipientKeypair = anchor.web3.Keypair.generate()
const levyRecipientKeypair = anchor.web3.Keypair.generate()
const attestKeypair = anchor.web3.Keypair.generate()
let schemaUID: PublicKey
let mintAcount: PublicKey
let attesterTokenAccount: PublicKey
let levyTokenAccount: PublicKey
before(async () => {
console.log('Starting setup...')
const airdropSig1 = await provider.connection.requestAirdrop(
authorityKeypair.publicKey,
anchor.web3.LAMPORTS_PER_SOL
)
console.log('Airdropped SOL to authority:', airdropSig1)
await provider.connection.confirmTransaction(airdropSig1)
const airdropSig2 = await provider.connection.requestAirdrop(
unauthorityKeypair.publicKey,
anchor.web3.LAMPORTS_PER_SOL
)
console.log('Airdropped SOL to unauthority:', airdropSig2)
await provider.connection.confirmTransaction(airdropSig2)
const airdropSig3 = await provider.connection.requestAirdrop(
attestKeypair.publicKey,
anchor.web3.LAMPORTS_PER_SOL
)
console.log('Airdropped SOL to attester:', airdropSig3)
await provider.connection.confirmTransaction(airdropSig3)
mintAcount = await createMint(
provider.connection,
authorityKeypair,
authorityKeypair.publicKey,
null,
0
)
console.log('Created mint account:', mintAcount.toBase58())
attesterTokenAccount = await createAccount(
provider.connection,
authorityKeypair,
mintAcount,
attestKeypair.publicKey
)
console.log('Created attester token account:', attesterTokenAccount.toBase58())
levyTokenAccount = await createAccount(
provider.connection,
authorityKeypair,
mintAcount,
levyRecipientKeypair.publicKey
)
console.log('Created levy token account:', levyTokenAccount.toBase58())
await mintTo(
provider.connection,
authorityKeypair,
mintAcount,
attesterTokenAccount,
authorityKeypair,
10_000
)
console.log('Minted tokens to attester token account')
})
it('user can register authority', async () => {
console.log('Registering authority...')
const [authorityRecordPDA, authorityRecordBump] = PublicKey.findProgramAddressSync(
[Buffer.from('authority'), authorityKeypair.publicKey.toBuffer()],
attest.programId
)
console.log('Derived authorityRecord PDA:', authorityRecordPDA.toBase58())
await attest.methods
.registerAuthority()
.accounts({
authority: authorityKeypair.publicKey,
})
.signers([authorityKeypair])
.rpc()
console.log('Authority registered successfully')
const authorityAccount = await attest.account.authorityRecord.fetch(
authorityRecordPDA
)
console.log('Fetched authority account:', authorityAccount)
expect(authorityAccount.authority.toBase58()).to.equal(authorityKeypair.publicKey.toBase58())
expect(authorityAccount.isVerified).to.be.false
})
it('authority can create schema with token levy', async () => {
console.log('Creating schema with token levy...')
const schemaName = 'example-schema'
const schemaContent = '{"name": "example", "type": "object"}'
const resolverAddress = null
const revocable = true
const levy = {
amount: new anchor.BN(10),
asset: mintAcount,
recipient: authorityKeypair.publicKey,
}
const [authorityRecordPDA, authorityRecordBump] = PublicKey.findProgramAddressSync(
[Buffer.from('authority'), authorityKeypair.publicKey.toBuffer()],
attest.programId
)
console.log('Derived authorityRecord PDA:', authorityRecordPDA.toBase58())
const [schemaDataPDA] = await PublicKey.findProgramAddress(
[Buffer.from('schema'), authorityKeypair.publicKey.toBuffer(), Buffer.from(schemaName)],
attest.programId
)
console.log('Derived schemaData PDA:', schemaDataPDA.toBase58())
await attest.methods
.createSchema(schemaName, schemaContent, resolverAddress, revocable, levy)
.accounts({
deployer: authorityKeypair.publicKey,
authorityRecord: authorityRecordPDA,
})
.signers([authorityKeypair])
.rpc()
console.log('Schema created successfully')
const schemeDataAccount = await attest.account.schemaData.fetch(schemaDataPDA)
console.log('Fetched schema data account:', schemeDataAccount)
expect(schemeDataAccount.levy.amount.toNumber()).to.equal(10)
expect(schemeDataAccount.levy.recipient.toBase58()).to.equal(
authorityKeypair.publicKey.toBase58()
)
})
it('attester can attest with token levy', async () => {
console.log('Attesting with token levy...')
const data = 'This is a test attestation data.'
const refUid = null
const expirationTime = null
const revocable = true
const schemaName = 'example-schema'
const [schemaDataPDA] = await PublicKey.findProgramAddress(
[Buffer.from('schema'), authorityKeypair.publicKey.toBuffer(), Buffer.from(schemaName)],
attest.programId
)
console.log('Derived schemaData PDA:', schemaDataPDA.toBase58())
const [attestationPDA] = await PublicKey.findProgramAddress(
[
Buffer.from('attestation'),
schemaDataPDA.toBuffer(),
recipientKeypair.publicKey.toBuffer(),
attestKeypair.publicKey.toBuffer(),
],
attest.programId
)
console.log('Derived attestation PDA:', attestationPDA.toBase58())
await attest.methods
.attest(data, refUid, expirationTime, revocable)
.accounts({
attester: attestKeypair.publicKey,
recipient: recipientKeypair.publicKey,
levyReceipent: levyRecipientKeypair.publicKey,
mintAccount: mintAcount,
schemaData: schemaDataPDA,
})
.signers([attestKeypair])
.rpc()
console.log('Attestation completed successfully')
const levyTokenAccountBalance = await provider.connection.getTokenAccountBalance(
levyTokenAccount
)
console.log('Levy token account balance:', levyTokenAccountBalance.value.amount)
expect(levyTokenAccountBalance.value.amount).to.equal('10')
// Store schema UID for later tests
schemaUID = schemaDataPDA
})
it('attester can revoke attestation', async () => {
console.log('Revoking attestation...')
const [attestationPDA] = await PublicKey.findProgramAddress(
[
Buffer.from('attestation'),
schemaUID.toBuffer(),
recipientKeypair.publicKey.toBuffer(),
attestKeypair.publicKey.toBuffer(),
],
attest.programId
)
console.log('Derived attestation PDA:', attestationPDA.toBase58())
// Fetch attestation account before revocation
const attestationBefore = await attest.account.attestation.fetch(attestationPDA)
console.log('Attestation before revocation:', attestationBefore)
expect(attestationBefore.revocationTime).to.be.null
// Revoke the attestation
await attest.methods
.revokeAttestation(schemaUID, recipientKeypair.publicKey)
.accounts({
attester: attestKeypair.publicKey,
attestation: attestationPDA,
})
.signers([attestKeypair])
.rpc()
console.log('Attestation revoked successfully')
// Fetch attestation account after revocation
const attestationAfter = await attest.account.attestation.fetch(attestationPDA)
console.log('Attestation after revocation:', attestationAfter)
expect(attestationAfter.revocationTime).to.be.not_null
// Try to revoke again, should fail with AlreadyRevoked error
try {
await attest.methods
.revokeAttestation(schemaUID, recipientKeypair.publicKey)
.accounts({
attester: attestKeypair.publicKey,
attestation: attestationPDA,
})
.signers([attestKeypair])
.rpc()
// assert.fail('Should have thrown AlreadyRevoked error')
} catch (error) {
console.error(error)
expect(error.message).to.include('AlreadyRevoked')
}
})
})