Skip to content

Latest commit

Β 

History

History
489 lines (370 loc) Β· 10.1 KB

File metadata and controls

489 lines (370 loc) Β· 10.1 KB

Write Functions Guide - State-Changing Operations

Complete guide for using the write functions script to perform state-changing operations on Certifi.

πŸ“ Overview

The write-functions.js script provides a complete workflow for:

  1. Registering institutions
  2. Managing verifiers
  3. Issuing credentials
  4. Verifying credentials
  5. Revoking credentials

πŸš€ Quick Start

Run Default Workflow

npm run write

This will execute a complete example workflow:

  1. Register an institution
  2. Issue a credential
  3. Verify the credential

Run Specific Functions

Edit scripts/write-functions.js and uncomment the operations you need.

πŸ“‹ Available Functions

Institution Functions

1. Register Institution

await registerInstitution(
  'University of Lagos',
  'Nigeria',
  'REG-UNILAG-2024',
  'https://metadata.example.com/unilag'
);

Parameters:

  • name (string): Institution name
  • country (string): Country name
  • regNumber (string): Registration number
  • metadataUri (string): URI to institution metadata

Returns: Transaction ID

Gas Cost: ~0.01-0.05 STX

2. Add Verifier

await addVerifier('SP2VERIFIER_ADDRESS');

Parameters:

  • verifierAddress (string): Stacks address of verifier

Returns: Transaction ID

Gas Cost: ~0.01-0.05 STX

Note: Only contract owner can add verifiers

3. Verify Institution

await verifyInstitution(0);

Parameters:

  • institutionId (uint): ID of institution to verify

Returns: Transaction ID

Gas Cost: ~0.01-0.05 STX

Note: Only verifiers can verify institutions

Credential Functions

4. Issue Credential

const result = await issueCredential(
  'SP2STUDENT_ADDRESS',
  0,
  'Bachelor of Science in Computer Science',
  'Student: John Doe, Program: BSc CS, Year: 2024, Grade: A',
  'https://metadata.example.com/credential-001'
);

// Returns:
// {
//   txid: 'transaction-id',
//   hash: 'credential-hash'
// }

Parameters:

  • studentAddress (string): Stacks address of student
  • institutionId (uint): ID of issuing institution
  • credentialType (string): Type of credential
  • credentialData (string): Credential data (will be hashed)
  • metadataUri (string): URI to credential metadata

Returns: Object with transaction ID and credential hash

Gas Cost: ~0.01-0.05 STX

Note: Credential data is automatically hashed using SHA-256

5. Verify Credential

await verifyCredential(0);

Parameters:

  • credentialId (uint): ID of credential to verify

Returns: Transaction ID

Gas Cost: ~0.01-0.05 STX

6. Revoke Credential

await revokeCredential(0, 'Fraudulent credential');

Parameters:

  • credentialId (uint): ID of credential to revoke
  • reason (string): Reason for revocation

Returns: Transaction ID

Gas Cost: ~0.01-0.05 STX

πŸ”„ Complete Workflow Example

Step 1: Register Institution

const institutionTxId = await registerInstitution(
  'University of Lagos',
  'Nigeria',
  'REG-UNILAG-2024',
  'https://metadata.example.com/unilag'
);

Step 2: Add Verifier (Optional)

const verifierTxId = await addVerifier('SP2VERIFIER_ADDRESS');

Step 3: Verify Institution (Optional)

const verifyInstTxId = await verifyInstitution(0);

Step 4: Issue Credential

const credentialResult = await issueCredential(
  'SP2STUDENT_ADDRESS',
  0,
  'Bachelor of Science in Computer Science',
  'Student: John Doe, Program: BSc CS, Year: 2024, Grade: A',
  'https://metadata.example.com/credential-001'
);

console.log('Credential Hash:', credentialResult.hash);

Step 5: Verify Credential

const verifyCredTxId = await verifyCredential(0);

Step 6: Revoke Credential (If Needed)

const revokeTxId = await revokeCredential(0, 'Fraudulent credential');

🎯 Usage Patterns

Pattern 1: Simple Institution Registration

# Edit scripts/write-functions.js
# Comment out all steps except registerInstitution

npm run write

Pattern 2: Complete Credential Lifecycle

# Run default workflow (already includes all steps)
npm run write

Pattern 3: Custom Workflow

// Edit scripts/write-functions.js

async function customWorkflow() {
  // Your custom operations
  const instTxId = await registerInstitution(...);
  const credTxId = await issueCredential(...);
  const verifyTxId = await verifyCredential(...);
}

customWorkflow();

πŸ“Š Gas Optimization

Minimize Gas Costs

  1. Batch Operations

    • Combine multiple operations in one script run
    • Reduces overhead
  2. Test on Testnet First

    STACKS_NETWORK=testnet npm run write
  3. Monitor Gas Prices

    • Check Stacks Explorer before mainnet operations
    • Deploy during low-gas periods
  4. Use Read-Only Calls First

    npm run mainnet-interact

    Check data before making state changes

Typical Costs

Operation Cost
Register Institution 0.01-0.05 STX
Add Verifier 0.01-0.05 STX
Verify Institution 0.01-0.05 STX
Issue Credential 0.01-0.05 STX
Verify Credential 0.01-0.05 STX
Revoke Credential 0.01-0.05 STX
Total for all 6 0.06-0.30 STX

πŸ” Security Considerations

Before Mainnet

  1. Test on Testnet

    STACKS_NETWORK=testnet npm run write
  2. Verify Addresses

    • Double-check all Stacks addresses
    • Ensure correct institution/credential IDs
  3. Review Metadata

    • Verify metadata URIs are correct
    • Ensure metadata is accessible

On Mainnet

  1. Use Correct Network

    STACKS_NETWORK=mainnet npm run write
  2. Monitor Transactions

    • Get transaction ID from output
    • Visit Stacks Explorer
    • Wait for confirmation
  3. Keep Records

    • Save transaction IDs
    • Document credential hashes
    • Maintain audit trail

πŸ” Monitoring Transactions

Get Transaction ID

βœ… INSTITUTION REGISTERED!
Transaction ID: 0x1234567890abcdef...

Monitor on Explorer

  1. Visit: https://explorer.stacks.co/
  2. Search transaction ID
  3. Wait for confirmation (10-30 minutes)

Check Credential Hash

Credential Hash: a1b2c3d4e5f6...

Save this for verification later.

πŸ› οΈ Customization

Add Custom Function

async function customOperation() {
  try {
    console.log(`\nπŸ“ CUSTOM OPERATION`);
    console.log(`${'─'.repeat(70)}`);

    const txOptions = {
      contractAddress: INSTITUTIONS_CONTRACT.split('.')[0],
      contractName: INSTITUTIONS_CONTRACT.split('.')[1],
      functionName: 'your-function',
      functionArgs: [
        // Your arguments
      ],
      senderKey: DEPLOYER_KEY,
      network: NETWORK,
      anchorMode: 'onChainOnly',
    };

    const transaction = await makeContractCall(txOptions);
    const broadcastResponse = await broadcastTransaction(transaction, NETWORK);

    console.log(`\nβœ… OPERATION COMPLETE!`);
    console.log(`Transaction ID: ${broadcastResponse.txid}`);

    return broadcastResponse.txid;
  } catch (error) {
    console.error(`\n❌ Error:`, error.message);
    throw error;
  }
}

Export Custom Function

module.exports = {
  registerInstitution,
  addVerifier,
  verifyInstitution,
  issueCredential,
  verifyCredential,
  revokeCredential,
  customOperation, // Add your function
};

πŸ“ž Troubleshooting

"Insufficient balance"

  • Check your STX balance
  • Add more STX to your account

"Unauthorized"

  • Verify you have correct permissions
  • Check if you're the contract owner/verifier

"Transaction stuck"

  • Wait 30+ minutes
  • Check network status
  • Try again with higher gas

"Contract not found"

  • Verify contract addresses in deployments/deployment.json
  • Ensure you're on correct network

πŸŽ“ Examples

Example 1: Register Multiple Institutions

async function registerMultiple() {
  const institutions = [
    {
      name: 'University of Lagos',
      country: 'Nigeria',
      regNumber: 'REG-UNILAG-2024',
      uri: 'https://metadata.example.com/unilag'
    },
    {
      name: 'University of Ibadan',
      country: 'Nigeria',
      regNumber: 'REG-UI-2024',
      uri: 'https://metadata.example.com/ui'
    }
  ];

  for (const inst of institutions) {
    await registerInstitution(
      inst.name,
      inst.country,
      inst.regNumber,
      inst.uri
    );
  }
}

Example 2: Issue Multiple Credentials

async function issueMultiple() {
  const credentials = [
    {
      student: 'SP2STUDENT1',
      type: 'Bachelor of Science',
      data: 'Student 1 data'
    },
    {
      student: 'SP2STUDENT2',
      type: 'Master of Science',
      data: 'Student 2 data'
    }
  ];

  for (const cred of credentials) {
    await issueCredential(
      cred.student,
      0,
      cred.type,
      cred.data,
      'https://metadata.example.com/credential'
    );
  }
}

✨ Features

βœ… Automatic contract address loading βœ… SHA-256 credential hashing βœ… Transaction monitoring βœ… Error handling βœ… Network detection βœ… Detailed logging βœ… Exportable functions βœ… Easy customization

πŸ“š Related Documentation

🎯 Next Steps

  1. Test on Testnet

    STACKS_NETWORK=testnet npm run write
  2. Review Transactions

    • Check Stacks Explorer
    • Verify operations succeeded
  3. Deploy to Mainnet

    STACKS_NETWORK=mainnet npm run write
  4. Monitor and Maintain

    • Keep transaction records
    • Monitor contract health

πŸ“„ Summary

The write functions script provides a complete, gas-optimized way to perform state-changing operations on Certifi. Use it to:

  • Register institutions
  • Manage verifiers
  • Issue credentials
  • Verify credentials
  • Revoke credentials

Always test on testnet first, monitor gas prices, and keep detailed records of all transactions!