Skip to content

Commit

Permalink
add framework to test cred with smart contract
Browse files Browse the repository at this point in the history
  • Loading branch information
teddyjfpender committed Aug 28, 2023
1 parent 84073c3 commit e071e95
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 1 deletion.
74 changes: 74 additions & 0 deletions packages/credentials/test/contractInteraction.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { KYCDepositCompliantContract } from './contracts/KYCDepositCompliantContract';
import { Field, Mina, PrivateKey, PublicKey, AccountUpdate } from 'snarkyjs';
import { loadProofJSON, convertProof } from './utils/utils';
/*
* This file tests how to test the `KYCDepositCompliantContract` smart contract.
* See https://docs.minaprotocol.com/zkapps for more info.
*/

let proofsEnabled = false; // Set proofsEnabled to true for testing

describe('KYCDepositCompliantContract', () => {
let deployerAccount: PublicKey;
let deployerKey: PrivateKey;
let userOneAccount: PublicKey;
let userOneKey: PrivateKey;
let zkAppAddress: PublicKey;
let zkAppPrivateKey: PrivateKey;
let zkApp: KYCDepositCompliantContract;

beforeAll(async () => {
if (proofsEnabled) await KYCDepositCompliantContract.compile();
});

beforeEach(() => {
const local = Mina.LocalBlockchain({ proofsEnabled });
Mina.setActiveInstance(local);
if (local.testAccounts[0] && local.testAccounts[1]) {
({ privateKey: deployerKey, publicKey: deployerAccount } = local.testAccounts[0]);
({ privateKey: userOneKey, publicKey: userOneAccount } = local.testAccounts[1]);
} else {
throw new Error('Test accounts are not defined');
}
zkAppPrivateKey = PrivateKey.random();
zkAppAddress = zkAppPrivateKey.toPublicKey();
zkApp = new KYCDepositCompliantContract(zkAppAddress);
});

async function localDeploy() {
const deployTxn = await Mina.transaction(deployerAccount, () => {
AccountUpdate.fundNewAccount(deployerAccount);
zkApp.deploy();
});

await deployTxn.prove();
await deployTxn.sign([deployerKey, zkAppPrivateKey]).send();
}

it('deploys the `KYCDepositCompliantContract` smart contract', async () => {
await localDeploy();
const totalDeposit = await zkApp.depositTotal.get();
expect(totalDeposit).toEqual(Field(0));
});
it('A wallet loads an attestation proof type it is knows of, and increments the depositTotal value of the contract', async () => {
// Load AttestationProof
const attestationProofJSON = loadProofJSON();
const attestationProof = convertProof(attestationProofJSON);
expect(attestationProof).toBeDefined();
// Define amount to deposit
const amount = Field(100);
// Deploy the zkApp
await localDeploy();
const initialDepositValue = await zkApp.depositTotal.get();

// post proof to the zkApp
const postProofTxn = await Mina.transaction(userOneAccount, () => {
zkApp.deposit(attestationProof, amount);
})
await postProofTxn.prove();
await postProofTxn.sign([userOneKey]).send();
console.log("new state", await zkApp.depositTotal.get());
expect(await zkApp.depositTotal.get()).toEqual(initialDepositValue.add(amount));
});

});
30 changes: 30 additions & 0 deletions packages/credentials/test/contracts/KYCDepositCompliantContract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Field, SmartContract, state, State, method} from 'snarkyjs';
import { AttestationProof } from '@herald-sdk/provable-programs';
/**
* Basic Example for a counter zkApp with recursion
* See https://docs.minaprotocol.com/zkapps for more info.
*/

export class KYCDepositCompliantContract extends SmartContract {

// on-chain version of our state. This will typically lag
// behind the version that's implicitly represented by the list of actions
@state(Field) depositTotal = State<Field>();

// initialize the value to 0
init() {
super.init();
this.depositTotal.set(Field(0));
}

@method deposit(proof: AttestationProof, amount: Field) {
// 1. assert the current counter value
this.depositTotal.getAndAssertEquals();
// 2. verify proof
proof.verify();
// 3. create new state
const newState = this.depositTotal.get().add(amount);;
// 4. update counter
this.depositTotal.set(newState);
}
}
2 changes: 1 addition & 1 deletion packages/credentials/test/credentialsConstruction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Credential Construction', () => {

beforeAll(() => {
issuerPrvKey = PrivateKey.fromBase58("EKDhdt1SX7i1cp7KZRzqVdJDYUf16HqM4bGpUzF98jSh3hzZTZLr");
subjectPrvKey = PrivateKey.fromBase58("EKE1c5UXWmKpzSZxkh67MPUeujYtoVppkGKrv3zC9CFXnWAzkktu")
subjectPrvKey = PrivateKey.fromBase58("EKE1c5UXWmKpzSZxkh67MPUeujYtoVppkGKrv3zC9CFXnWAzkktu");
claims = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
Expand Down
13 changes: 13 additions & 0 deletions packages/credentials/test/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import fs from 'fs';
import path from 'path';
import { AttestationProof } from '@herald-sdk/provable-programs';

// TODO: create generic utils for loading a proof from a file and converting it to a proof object
export function loadProofJSON(): string {
const proofJSON = JSON.parse(fs.readFileSync(path.join('test', 'test_proofs', 'attestationProof.json'), 'utf8'));
return JSON.stringify(proofJSON);
}
export function convertProof(proofJSON: string): AttestationProof {
const proof = AttestationProof.fromJSON(JSON.parse(proofJSON));
return proof;
}

0 comments on commit e071e95

Please sign in to comment.