npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

azkey-sdk

v0.2.0

Published

TypeScript SDK for Solana zkLogin proof generation and account management

Readme

azkey-sdk

TypeScript SDK for Solana zkLogin proof generation and account management.

Installation

npm install azkey-sdk
# or
pnpm add azkey-sdk

Quick Start

import { AccountManager } from 'azkey-sdk';

// Initialize
const manager = new AccountManager({
  googleClientId: 'your-client-id.apps.googleusercontent.com',
  solanaRpcUrl: 'https://api.mainnet-beta.solana.com'
});

// Get Google OAuth URL
const authUrl = manager.getAuthUrl();
window.location.href = authUrl;

// Handle OAuth callback
const code = new URLSearchParams(window.location.search).get('code');
const authResult = await manager.exchangeCode(code);

// Create account
const account = await manager.createAccount(authResult);
console.log('Account created:', account.address);
console.log('Session owner:', account.sessionOwner);

Features

OAuth Integration - Seamless Google Sign-In
Account Derivation - Deterministic account IDs from identity
ZK Proof Generation - Private proof generation (client-side)
Account Recovery - Recover accounts without seed phrases
Session Management - Ephemeral key management
TypeScript Support - Full type safety
Framework Agnostic - Works with any JavaScript framework

How It Works

Step 1: Authentication

User authenticates with Google, receiving a JWT.

Step 2: Account ID Derivation

SDK derives a unique, permanent account_id from the JWT:

account_id = hash(jwt.sub, jwt.aud)
  • jwt.sub = Google's unique user ID (private)
  • jwt.aud = Your app's OAuth client ID
  • Deterministic: same user always gets same account ID

Step 3: Proof Generation

Noir circuit generates a zero-knowledge proof:

  • ✓ JWT signature is valid
  • ✓ Account ID matches hash
  • ✓ Private inputs never revealed on-chain

Step 4: Account Creation

Solana program deployed with immutable account_id in account state.

Step 5: Session Management

Temporary session_owner key authorized to control account. Lost key? Use Google OAuth again to recover and set new owner.

API

AccountManager

Main entry point for account operations.

Constructor

new AccountManager(config: AccountConfig, provider?: string)

Config:

{
  googleClientId: string;      // Required: Google OAuth Client ID
  googleClientSecret?: string; // Optional: For server-side token exchange
  aztecRpcUrl?: string;        // Optional: Aztec RPC (default: localhost:8080)
  redirectUri?: string;        // Optional: OAuth callback URL
}

Methods

getAuthUrl(): string

const url = manager.getAuthUrl();
window.location.href = url;

Returns Google OAuth authorization URL.

exchangeCode(code: string): Promise

const authResult = await manager.exchangeCode(code);
// { idToken: "...", accessToken?: "...", ... }

Exchanges OAuth code for JWT and tokens.

createAccount(authResult: AuthResult): Promise

const account = await manager.createAccount(authResult);
// { address: "0x...", accountId: Field, sessionOwner: "0x...", txHash: "0x..." }

Creates new account on Aztec.

accountExistsForIdentity(authResult: AuthResult): Promise<AztecAddress | null>

const address = await manager.accountExistsForIdentity(authResult);
if (address) {
  // Account found, can recover
}

Checks if account exists for the given identity.

recoverAccount(authResult: AuthResult, address: AztecAddress): Promise

const account = await manager.recoverAccount(authResult, existingAddress);

Recovers existing account by setting new session owner.

Framework Integration

React

import { useEffect, useState } from 'react';
import { AccountManager } from 'azkey-sdk';

function GoogleSignIn() {
  const [manager] = useState(
    () => new AccountManager({ googleClientId: 'your-id' })
  );

  const handleSignIn = () => {
    window.location.href = manager.getAuthUrl();
  };

  return (
    <button onClick={handleSignIn}>
      Sign in with Google
    </button>
  );
}

Vue

<script setup>
import { ref } from 'vue';
import { AccountManager } from 'azkey-sdk';

const manager = new AccountManager({ googleClientId: 'your-id' });

const handleSignIn = () => {
  window.location.href = manager.getAuthUrl();
};
</script>

<template>
  <button @click="handleSignIn">Sign in with Google</button>
</template>

Svelte

<script>
  import { onMount } from 'svelte';
  import { AccountManager } from 'azkey-sdk';

  let manager;

  onMount(() => {
    manager = new AccountManager({ googleClientId: 'your-id' });
  });

  const handleSignIn = () => {
    window.location.href = manager.getAuthUrl();
  };
</script>

<button on:click={handleSignIn}>Sign in with Google</button>

Next.js / SvelteKit

For server-side token exchange:

// In server route
import { AccountManager } from 'azkey-sdk';

const manager = new AccountManager({
  googleClientId: process.env.GOOGLE_CLIENT_ID!,
  googleClientSecret: process.env.GOOGLE_CLIENT_SECRET!,
  aztecRpcUrl: process.env.AZTEC_RPC_URL
});

export async function POST(request) {
  const { code } = await request.json();
  const authResult = await manager.exchangeCode(code);
  // ... create account
  return Response.json(authResult);
}

Error Handling

try {
  const authResult = await manager.exchangeCode(code);
} catch (error) {
  if (error.message.includes('invalid_grant')) {
    // Code expired or already used
  } else if (error.message.includes('invalid_client')) {
    // Client ID/Secret incorrect
  } else if (error.message.includes('network')) {
    // Network error
  }
}

Best Practices

1. Secure Token Storage

// Don't store sensitive tokens in localStorage
// Use secure HTTP-only cookies if possible

// For demo: sessionStorage (cleared on tab close)
sessionStorage.setItem('session_owner', account.sessionOwner);

// Don't do this:
// localStorage.setItem('google_token', authResult.idToken);

2. Error Handling

try {
  const account = await manager.createAccount(authResult);
} catch (error) {
  console.error('Account creation failed:', error.message);
  // Show user-friendly error message
}

3. Account Recovery Flow

const authResult = await manager.exchangeCode(code);

// Check if account exists
const existing = await manager.accountExistsForIdentity(authResult);

if (existing) {
  // Recover existing account
  const account = await manager.recoverAccount(authResult, existing);
} else {
  // Create new account
  const account = await manager.createAccount(authResult);
}

4. Session Management

// After account creation, store ephemeral key securely
const account = await manager.createAccount(authResult);

// Sign transactions with session owner
const tx = /* ... */;
const signature = await signWithSessionOwner(tx, account.sessionOwner);

Testing

# Unit tests
pnpm test:unit

# Integration tests (requires Aztec sandbox)
RUN_INTEGRATION_TESTS=true pnpm test:integration

# All tests
pnpm test

Examples

Full examples available in GitHub:

  • React integration
  • Vue integration
  • Next.js integration
  • Plain JavaScript

Environment Variables

# Required
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com

# Optional
GOOGLE_CLIENT_SECRET=your-client-secret
AZTEC_RPC_URL=https://aztec-testnet.example.com

Troubleshooting

"Client not initialized"

Ensure AccountManager is initialized before calling methods:

const manager = new AccountManager({ googleClientId: '...' });
// Then use manager

"Invalid authorization code"

  • Code may have expired (valid for ~10 minutes)
  • Code may have already been used
  • Redirect URI may not match

"Contract deployment failed"

  • Aztec RPC may be unreachable
  • Account may already exist
  • Network gas price too low

"Session owner not working"

  • Ensure you're using the returned session owner from account creation
  • Session owner must be authorized in the account contract

Contributing

Found an issue? Open an issue

License

MIT - See LICENSE

Links