# GitHub - hidayatgp1/oracle: Oracle Mission

By [『EMT』🌘 🛸 (💙,🧡) .L2 .hft .lens (📦,💫) (🧢,🧢)](https://paragraph.com/@0x32123) · 2022-12-10

---

Mina zkApp: Oracle
------------------

This is tutorial to build Oracle of Mina Protocol Project.

Make New Project
----------------

Delete few files below

    rm src/Add.ts
    rm src/Add.test.ts
    rm src/interact.ts
    

Edit _index.ts_ file in _src_ folder

    import { OracleExample } from './OracleExample.js';
    
    export { OracleExample };
    

### Create new file in _src_ folder with name _CreditScoreOracle.ts_ and write

    import {
        Field,
        SmartContract,
        state,
        State,
        method,
        DeployArgs,
        Permissions,
        PublicKey,
        Signature,
        PrivateKey,
      } from 'snarkyjs';
      
      // The public key of our trusted data provider
      const ORACLE_PUBLIC_KEY =
        'B62qoAE4rBRuTgC42vqvEyUqCGhaZsW58SKVW4Ht8aYqP9UTvxFWBgy';
      
      export class OracleExample extends SmartContract {
        // Define contract state
        @state(PublicKey) oraclePublicKey = State<PublicKey>();
      
        // Define contract events
        events = {
            verified: Field,
          };
      
        deploy(args: DeployArgs) {
          super.deploy(args);
          this.setPermissions({
            ...Permissions.default(),
            editState: Permissions.proofOrSignature(),
          });
        }
      
        @method init(zkappKey: PrivateKey) {
          super.init(zkappKey);
          // Initialize contract state
          this.oraclePublicKey.set(PublicKey.fromBase58(ORACLE_PUBLIC_KEY));
      
          // Specify that caller should include signature with tx instead of proof
          this.requireSignature();
        }
      
        @method verify(id: Field, creditScore: Field, signature: Signature) {
          // Get the oracle public key from the contract state
          const oraclePublicKey = this.oraclePublicKey.get();
          this.oraclePublicKey.assertEquals(oraclePublicKey);
      
          // Evaluate whether the signature is valid for the provided data
          const validSignature = signature.verify(oraclePublicKey, [id, creditScore]);
      
          // Check that the signature is valid
          validSignature.assertTrue();
      
          // Check that the provided credit score is greater than 700
          creditScore.assertGte(Field(700));
      
          // Emit an event containing the verified users id
          this.emitEvent('verified', id);
      
        }
      }
    

### Create new file in _src_ folder with name _OracleExampleScaffold.ts_ and write

    import {
    Field,
    SmartContract,
    state,
    State,
    method,
    DeployArgs,
    Permissions,
    PublicKey,
    Signature,
    PrivateKey,
    } from 'snarkyjs';
    
    // The public key of our trusted data provider
    const ORACLE_PUBLIC_KEY =
    'B62qoAE4rBRuTgC42vqvEyUqCGhaZsW58SKVW4Ht8aYqP9UTvxFWBgy';
    
    export class OracleExample extends SmartContract {
    // Define contract state
    
    // Define contract events
    
    deploy(args: DeployArgs) {
      super.deploy(args);
      this.setPermissions({
        ...Permissions.default(),
        editState: Permissions.proofOrSignature(),
      });
    }
    
    @method init(zkappKey: PrivateKey) {
      super.init(zkappKey);
      // Initialize contract state
    
      // Specify that caller should include signature with tx instead of proof
      this.requireSignature();
    }
    
    @method verify(id: Field, creditScore: Field, signature: Signature) {
      // Get the oracle public key from the contract state
    
      // Evaluate whether the signature is valid for the provided data
    
      // Check that the signature is valid
    
      // Check that the provided credit score is greater than 700
    
      // Emit an event containing the verified users id
      
    }
    }
    

### Create new file in _src_ folder with name _OracleExample.ts_ and write

    import {
      Field,
      SmartContract,
      state,
      State,
      method,
      DeployArgs,
      Permissions,
      PublicKey,
      Signature,
      PrivateKey,
    } from 'snarkyjs';
    
    // The public key of our trusted data provider
    const ORACLE_PUBLIC_KEY =
      'B62qoAE4rBRuTgC42vqvEyUqCGhaZsW58SKVW4Ht8aYqP9UTvxFWBgy';
    
    export class OracleExample extends SmartContract {
      // Define contract state
      @state(PublicKey) oraclePublicKey = State<PublicKey>();
    
      // Define contract events
      events = {
        verified: Field,
      };
    
      deploy(args: DeployArgs) {
        super.deploy(args);
        this.setPermissions({
          ...Permissions.default(),
          editState: Permissions.proofOrSignature(),
        });
      }
    
      @method init(zkappKey: PrivateKey) {
        super.init(zkappKey);
        // Initialize contract state
        this.oraclePublicKey.set(PublicKey.fromBase58(ORACLE_PUBLIC_KEY));
        // Specify that caller should include signature with tx instead of proof
        this.requireSignature();
      }
    
      @method verify(id: Field, creditScore: Field, signature: Signature) {
        // Get the oracle public key from the contract state
        const oraclePublicKey = this.oraclePublicKey.get();
        this.oraclePublicKey.assertEquals(oraclePublicKey);
        // Evaluate whether the signature is valid for the provided data
        const validSignature = signature.verify(oraclePublicKey, [id, creditScore]);
        // Check that the signature is valid
        validSignature.assertTrue();
        // Check that the provided credit score is greater than 700
        creditScore.assertGte(Field(700));
        // Emit an event containing the verified users id
        this.emitEvent('verified', id);
      }
    }
    

### Create new file in _src_ folder with name _OracleExample.test.ts_ and write

    import { OracleExample } from './OracleExample';
    import {
      isReady,
      shutdown,
      Field,
      Mina,
      PrivateKey,
      PublicKey,
      AccountUpdate,
      Signature,
    } from 'snarkyjs';
    
    // The public key of our trusted data provider
    const ORACLE_PUBLIC_KEY =
      'B62qoAE4rBRuTgC42vqvEyUqCGhaZsW58SKVW4Ht8aYqP9UTvxFWBgy';
    
    let proofsEnabled = false;
    function createLocalBlockchain() {
      const Local = Mina.LocalBlockchain({ proofsEnabled });
      Mina.setActiveInstance(Local);
      return Local.testAccounts[0].privateKey;
    }
    
    async function localDeploy(
      zkAppInstance: OracleExample,
      zkAppPrivatekey: PrivateKey,
      deployerAccount: PrivateKey
    ) {
      const txn = await Mina.transaction(deployerAccount, () => {
        AccountUpdate.fundNewAccount(deployerAccount);
        zkAppInstance.deploy({ zkappKey: zkAppPrivatekey });
        zkAppInstance.init(zkAppPrivatekey);
      });
      await txn.prove();
      txn.sign([zkAppPrivatekey]);
      await txn.send();
    }
    
    describe('CreditScoreOracle', () => {
      let deployerAccount: PrivateKey,
        zkAppAddress: PublicKey,
        zkAppPrivateKey: PrivateKey;
    
      beforeAll(async () => {
        await isReady;
        if (proofsEnabled) OracleExample.compile();
      });
    
      beforeEach(async () => {
        deployerAccount = createLocalBlockchain();
        zkAppPrivateKey = PrivateKey.random();
        zkAppAddress = zkAppPrivateKey.toPublicKey();
      });
    
      afterAll(async () => {
        // `shutdown()` internally calls `process.exit()` which will exit the running Jest process early.
        // Specifying a timeout of 0 is a workaround to defer `shutdown()` until Jest is done running all tests.
        // This should be fixed with https://github.com/MinaProtocol/mina/issues/10943
        setTimeout(shutdown, 0);
      });
    
      it('generates and deploys the `CreditScoreOracle` smart contract', async () => {
        const zkAppInstance = new OracleExample(zkAppAddress);
        await localDeploy(zkAppInstance, zkAppPrivateKey, deployerAccount);
        const oraclePublicKey = zkAppInstance.oraclePublicKey.get();
        expect(oraclePublicKey).toEqual(PublicKey.fromBase58(ORACLE_PUBLIC_KEY));
      });
    
      describe('actual API requests', () => {
        it('emits an `id` event containing the users id if their credit score is above 700 and the provided signature is valid', async () => {
          const zkAppInstance = new OracleExample(zkAppAddress);
          await localDeploy(zkAppInstance, zkAppPrivateKey, deployerAccount);
    
          const response = await fetch(
            'https://mina-credit-score-signer-pe3eh.ondigitalocean.app/user/1'
          );
          const data = await response.json();
    
          const id = Field(data.data.id);
          const creditScore = Field(data.data.creditScore);
          const signature = Signature.fromJSON(data.signature);
    
          const txn = await Mina.transaction(deployerAccount, () => {
            zkAppInstance.verify(
              id,
              creditScore,
              signature ?? fail('something is wrong with the signature')
            );
          });
          await txn.prove();
          await txn.send();
    
          const events = await zkAppInstance.fetchEvents();
          const verifiedEventValue = events[0].event.toFields(null)[0];
          expect(verifiedEventValue).toEqual(id);
        });
    
        it('throws an error if the credit score is below 700 even if the provided signature is valid', async () => {
          const zkAppInstance = new OracleExample(zkAppAddress);
          await localDeploy(zkAppInstance, zkAppPrivateKey, deployerAccount);
    
          const response = await fetch(
            'https://mina-credit-score-signer-pe3eh.ondigitalocean.app/user/2'
          );
          const data = await response.json();
    
          const id = Field(data.data.id);
          const creditScore = Field(data.data.creditScore);
          const signature = Signature.fromJSON(data.signature);
    
          expect(async () => {
            await Mina.transaction(deployerAccount, () => {
              zkAppInstance.verify(
                id,
                creditScore,
                signature ?? fail('something is wrong with the signature')
              );
            });
          }).rejects;
        });
      });
    
      describe('hardcoded values', () => {
        it('emits an `id` event containing the users id if their credit score is above 700 and the provided signature is valid', async () => {
          const zkAppInstance = new OracleExample(zkAppAddress);
          await localDeploy(zkAppInstance, zkAppPrivateKey, deployerAccount);
    
          const id = Field(1);
          const creditScore = Field(787);
          const signature = Signature.fromJSON({
            r: '13209474117923890467777795933147746532722569254037337512677934549675287266861',
            s: '12079365427851031707052269572324263778234360478121821973603368912000793139475',
          });
    
          const txn = await Mina.transaction(deployerAccount, () => {
            zkAppInstance.verify(
              id,
              creditScore,
              signature ?? fail('something is wrong with the signature')
            );
          });
          await txn.prove();
          await txn.send();
    
          const events = await zkAppInstance.fetchEvents();
          const verifiedEventValue = events[0].event.toFields(null)[0];
          expect(verifiedEventValue).toEqual(id);
        });
    
        it('throws an error if the credit score is below 700 even if the provided signature is valid', async () => {
          const zkAppInstance = new OracleExample(zkAppAddress);
          await localDeploy(zkAppInstance, zkAppPrivateKey, deployerAccount);
    
          const id = Field(2);
          const creditScore = Field(536);
          const signature = Signature.fromJSON({
            r: '25163915754510418213153704426580201164374923273432613331381672085201550827220',
            s: '20455871399885835832436646442230538178588318835839502912889034210314761124870',
          });
    
          expect(async () => {
            await Mina.transaction(deployerAccount, () => {
              zkAppInstance.verify(
                id,
                creditScore,
                signature ?? fail('something is wrong with the signature')
              );
            });
          }).rejects;
        });
    
        it('throws an error if the credit score is above 700 and the provided signature is invalid', async () => {
          const zkAppInstance = new OracleExample(zkAppAddress);
          await localDeploy(zkAppInstance, zkAppPrivateKey, deployerAccount);
    
          const id = Field(1);
          const creditScore = Field(787);
          const signature = Signature.fromJSON({
            r: '26545513748775911233424851469484096799413741017006352456100547880447752952428',
            s: '7381406986124079327199694038222605261248869991738054485116460354242251864564',
          });
    
          expect(async () => {
            await Mina.transaction(deployerAccount, () => {
              zkAppInstance.verify(
                id,
                creditScore,
                signature ?? fail('something is wrong with the signature')
              );
            });
          }).rejects;
        });
      });
    });
    

Run Build
---------

Update Browserlist
------------------

    npx browserslist@latest --update-db
    

##Link with Repository Github Make new repository on Github and run

    git remote add origin *<your-repo-url>*
    git push -u origin main
    

Run The Test
------------

Run The Test with Command

OUTPUT
------

You might see something like this in output, thet it means you done!

![image](https://storage.googleapis.com/papyrus_images/ee9eb4b7d566f6dbc950b45230dbff2db9553fb308b6618cc8e27a4e754144ca.png)

image

License
-------

[https://github.com/hidayatgp1/oracle/blob/main/LICENSE](https://github.com/hidayatgp1/oracle/blob/main/LICENSE)

---

*Originally published on [『EMT』🌘 🛸 (💙,🧡) .L2 .hft .lens (📦,💫) (🧢,🧢)](https://paragraph.com/@0x32123/github-hidayatgp1-oracle-oracle-mission)*
