Integration Guides

Comprehensive step-by-step tutorials for integrating zkVault into your application. From basic vault creation to advanced cross-chain deployment.

Creating Your First Vault

Step 1: Install and Initialize SDK

npm install @vault-protocol/sdk ethers

import { VaultProtocolSDK } from '@vault-protocol/sdk';
import { ethers } from 'ethers';

// Connect wallet
const provider = new ethers.providers.Web3Provider(window.ethereum);
await provider.send("eth_requestAccounts", []);
const signer = provider.getSigner();

// Initialize SDK
const sdk = new VaultProtocolSDK({
  provider,
  signer,
  network: 'opbnb',
  apiUrl: 'https://api.vaultprotocol.ai',
  litNetwork: 'datil-test',
});

Step 2: Configure Vault Settings

const vaultConfig = {
  name: "My Crypto Inheritance Vault",
  releaseType: "DEADMAN", // or "SCHEDULED", "HYBRID"
  checkInPeriod: 90 * 24 * 60 * 60, // 90 days in seconds
  recipients: [
    "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", // Beneficiary 1
    "0x1234567890abcdef1234567890abcdef12345678"  // Beneficiary 2
  ],
  encrypted: true,
  metadata: {
    description: "Emergency wallet recovery for family",
    tags: ["inheritance", "emergency", "family"]
  }
};

Tip: Use DEADMAN for emergency recovery, SCHEDULED for time-locked releases, HYBRID for both conditions.

Step 3: Create Vault

try {
  const vault = await sdk.vaultManager.createVault(vaultConfig);

  console.log('✓ Vault created successfully!');
  console.log('Vault ID:', vault.id);
  console.log('Transaction Hash:', vault.transactionHash);
  console.log('Created At:', new Date(vault.createdAt * 1000));

  // Store vault ID for future reference
  localStorage.setItem('vaultId', vault.id);

} catch (error) {
  console.error('Vault creation failed:', error.message);
}

Step 4: Upload Encrypted Content

// Prepare sensitive content (e.g., seed phrase)
const seedPhrase = "word1 word2 word3 ... word24";

// Upload with encryption
const contentCID = await sdk.vaultManager.uploadContent(vault.id, {
  data: seedPhrase,
  encrypted: true,
  storageLocation: 'arweave', // Permanent storage
  contentType: 'text/plain',
  metadata: {
    walletType: 'BIP39',
    description: 'Main wallet seed phrase',
    createdAt: Date.now()
  }
});

console.log('✓ Content uploaded and encrypted');
console.log('Content CID:', contentCID);

// For JSON data (wallet configurations, private keys, etc.)
const walletConfig = {
  mainWallet: { address: '0x...', privateKey: 'encrypted...' },
  subWallets: [...]
};

const jsonCID = await sdk.vaultManager.uploadContent(vault.id, {
  data: JSON.stringify(walletConfig, null, 2),
  encrypted: true,
  storageLocation: 'arweave',
  contentType: 'application/json'
});

Step 5: Set Up Deadman Switch

await sdk.timeManager.configureDeadmanSwitch(
  vault.id,
  90 * 24 * 60 * 60,  // Check-in period: 90 days
  7 * 24 * 60 * 60    // Grace period: 7 days after trigger
);

// Perform initial check-in
await sdk.timeManager.checkIn(vault.id);

console.log('✓ Deadman switch configured');
console.log('Next check-in due: 90 days from now');

Managing Beneficiaries

Update Beneficiary Shares

// Define beneficiaries with percentage shares
const beneficiaries = [
  { address: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", share: 50 }, // 50%
  { address: "0x1234567890abcdef1234567890abcdef12345678", share: 30 }, // 30%
  { address: "0xabcdef1234567890abcdef1234567890abcdef12", share: 20 }  // 20%
];

// Update vault beneficiaries
await sdk.vaultManager.updateBeneficiaries(
  vaultId,
  beneficiaries.map(b => b.address),
  beneficiaries.map(b => b.share * 100) // Convert to basis points
);

console.log('✓ Beneficiaries updated');

Note: Shares must total 100%. Use basis points internally (10000 = 100%).

Add Emergency Contact

// Get current vault
const vault = await sdk.vaultManager.getVault(vaultId);

// Add new beneficiary (e.g., trusted friend for emergency)
const updatedBeneficiaries = [
  ...vault.beneficiaries,
  {
    address: "0xnewbeneficiary...",
    share: 1000 // 10%
  }
];

// Adjust existing shares proportionally
const totalNewShares = updatedBeneficiaries.reduce((sum, b) => sum + b.share, 0);
const normalizedBeneficiaries = updatedBeneficiaries.map(b => ({
  address: b.address,
  share: Math.floor((b.share / totalNewShares) * 10000)
}));

await sdk.vaultManager.updateBeneficiaries(
  vaultId,
  normalizedBeneficiaries.map(b => b.address),
  normalizedBeneficiaries.map(b => b.share)
);

Check-in Workflows

Manual Check-in

async function performCheckIn(vaultId) {
  try {
    await sdk.timeManager.checkIn(vaultId);

    const vault = await sdk.vaultManager.getVault(vaultId);
    const nextCheckInTime = vault.lastCheckIn + vault.checkInPeriod;
    const nextCheckInDate = new Date(nextCheckInTime * 1000);

    console.log('✓ Check-in successful');
    console.log('Next check-in due:', nextCheckInDate.toLocaleString());

    return { success: true, nextCheckInDate };
  } catch (error) {
    console.error('Check-in failed:', error.message);
    return { success: false, error };
  }
}

Automated Check-in System

// Option 1: Client-side interval (not recommended for production)
function setupAutoCheckIn(vaultId) {
  const intervalId = setInterval(async () => {
    await sdk.timeManager.checkIn(vaultId);
    console.log('Automatic check-in performed');
  }, 30 * 24 * 60 * 60 * 1000); // Every 30 days

  return () => clearInterval(intervalId);
}

// Option 2: Server-side cron job (recommended)
// In your backend:
import cron from 'node-cron';

// Run daily at 9 AM
cron.schedule('0 9 * * *', async () => {
  const vaults = await getVaultsNeedingCheckIn();

  for (const vault of vaults) {
    try {
      await sdk.timeManager.checkIn(vault.id);
      await notifyOwner(vault.owner, 'Check-in successful');
    } catch (error) {
      await notifyOwner(vault.owner, 'Check-in failed', error);
    }
  }
});

// Option 3: Chainlink Automation (fully decentralized)
// See smart contract integration guide for Chainlink Keepers setup

Check-in Reminders

async function checkAndNotify(vaultId) {
  const vault = await sdk.vaultManager.getVault(vaultId);
  const now = Math.floor(Date.now() / 1000);
  const timeSinceLastCheckIn = now - vault.lastCheckIn;
  const timeUntilTrigger = vault.checkInPeriod - timeSinceLastCheckIn;

  // Send reminder at 7 days before trigger
  if (timeUntilTrigger <= 7 * 24 * 60 * 60 && timeUntilTrigger > 0) {
    const daysRemaining = Math.floor(timeUntilTrigger / (24 * 60 * 60));

    await sendNotification({
      to: vault.owner,
      title: "⚠️ Check-in Reminder",
      message: `Your vault "${vault.name}" needs check-in in ${daysRemaining} days`,
      priority: "high",
      actions: [
        { label: "Check In Now", url: `https://app.vaultprotocol.ai/vault/${vaultId}/checkin` }
      ]
    });
  }
}

Cross-Chain Deployment

Deploy to Multiple Chains

import { ChainId } from '@vault-protocol/sdk';

// Deploy vault to opBNB, Ethereum, and Polygon
const deployment = await sdk.crossChainClient.deployVaultCrossChain(
  {
    name: "Multi-Chain Inheritance Vault",
    releaseType: "DEADMAN",
    checkInPeriod: 90 * 24 * 60 * 60,
    recipients: ["0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"],
    encrypted: true
  },
  [ChainId.OPBNB, ChainId.ETHEREUM, ChainId.POLYGON]
);

console.log('Primary vault (opBNB):', deployment.primaryVaultId);

// Monitor deployment status
deployment.crossChainVaults.forEach(vault => {
  console.log(`Chain ${vault.chainId}: ${vault.status}`);
  console.log(`  Vault ID: ${vault.vaultId}`);
  console.log(`  Transaction: ${vault.transactionHash}`);
});

Sync Vault State Across Chains

// Perform check-in on primary chain (opBNB)
await sdk.timeManager.checkIn(vaultId);

// Sync to other chains via LayerZero
await sdk.crossChainClient.syncVaultState(
  vaultId,
  ChainId.ETHEREUM
);

await sdk.crossChainClient.syncVaultState(
  vaultId,
  ChainId.POLYGON
);

console.log('✓ Vault state synced across all chains');

// Verify sync
const ethereumVault = await sdk.vaultManager.getVault(vaultId, {
  chainId: ChainId.ETHEREUM
});
console.log('Ethereum last check-in:', ethereumVault.lastCheckIn);

Notification Integration

Push Protocol Setup

import * as PushAPI from '@pushprotocol/restapi';

// Initialize Push Protocol
const pushUser = await PushAPI.user.create({
  account: userAddress,
  env: 'prod'
});

// Subscribe to vault notifications
await PushAPI.channels.subscribe({
  signer,
  channelAddress: 'eip155:1:0xVaultProtocolChannel',
  userAddress,
  env: 'prod'
});

// Send notification on vault trigger
async function notifyVaultTrigger(vaultId, vault) {
  await PushAPI.payloads.sendNotification({
    signer,
    type: 1, // Broadcast
    identityType: 2, // Direct payload
    notification: {
      title: "🔓 Vault Triggered",
      body: `Your vault "${vault.name}" has been triggered and is ready for unlock.`
    },
    payload: {
      title: "Vault Triggered",
      body: `Vault "${vault.name}" (ID: ${vaultId}) has been triggered.`,
      cta: `https://app.vaultprotocol.ai/vault/${vaultId}`,
      img: ''
    },
    channel: 'eip155:1:0xVaultProtocolChannel',
    env: 'prod'
  });
}

Telegram Bot Integration

// Backend: Telegram bot setup
import TelegramBot from 'node-telegram-bot-api';

const bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN, { polling: true });

// Link wallet to Telegram
bot.onText(/\/start (.+)/, async (msg, match) => {
  const chatId = msg.chat.id;
  const walletAddress = match[1];

  await linkWalletToTelegram(walletAddress, chatId);
  bot.sendMessage(chatId, '✓ Wallet linked! You will receive vault notifications here.');
});

// Send vault notification
async function sendTelegramNotification(vaultOwner, message) {
  const chatId = await getTelegramChatId(vaultOwner);
  if (chatId) {
    await bot.sendMessage(chatId, message, {
      reply_markup: {
        inline_keyboard: [[
          { text: '🔍 View Vault', url: `https://app.vaultprotocol.ai/vault/${vaultId}` },
          { text: '✅ Check In', callback_data: `checkin_${vaultId}` }
        ]]
      }
    });
  }
}

Storage Configuration

Arweave (Permanent Storage)

// Best for: Seed phrases, private keys, critical documents
const arweaveCID = await sdk.vaultManager.uploadContent(vaultId, {
  data: seedPhrase,
  encrypted: true,
  storageLocation: 'arweave',
  contentType: 'text/plain'
});

// Pros: Permanent, immutable, one-time fee
// Cons: Higher upfront cost (~$0.50-5 per MB)

IPFS (Temporary Storage)

// Best for: Metadata, non-critical data, frequent updates
const ipfsCID = await sdk.vaultManager.uploadContent(vaultId, {
  data: vaultMetadata,
  encrypted: false,
  storageLocation: 'ipfs',
  contentType: 'application/json'
});

// Pros: Fast, cheap, easy updates
// Cons: Requires pinning, not permanent by default
// Recommendation: Use with Pinata or Infura pinning service

Ceramic (Dynamic Data)

// Best for: Vault metadata, beneficiary lists, check-in logs
const ceramicStreamId = await sdk.vaultManager.uploadContent(vaultId, {
  data: {
    beneficiaries: [...],
    checkInHistory: [...],
    lastUpdated: Date.now()
  },
  encrypted: false,
  storageLocation: 'ceramic',
  contentType: 'application/json'
});

// Pros: Mutable, version-controlled, decentralized
// Cons: Requires DID authentication, slightly slower

Gas Optimization Tips

Choose the Right Network

opBNB Mainnet$0.001/tx → Best for frequent operations
Polygon$0.01-0.05/tx → Good balance
Ethereum$5-50/tx → High-value vaults only

Batch Operations

// ❌ Bad: Multiple transactions
for (const vaultId of vaultIds) {
  await sdk.timeManager.checkIn(vaultId); // Separate tx for each
}

// ✅ Good: Single batched transaction
await sdk.timeManager.batchCheckIn(vaultIds); // One tx for all

// Gas savings: ~60% for 5+ vaults

Use VaultFactory

// ❌ Bad: Direct deployment (~500K gas)
const vault = await vaultContract.deploy(...);

// ✅ Good: Factory pattern (~50K gas, 90% savings)
const vault = await vaultFactory.deployVault(...);

Off-Chain Data Storage

// ❌ Bad: Store large data on-chain
await vaultManager.setContent(vaultId, largeJSONString);
// Cost: ~$50-500 on Ethereum

// ✅ Good: Store CID only
const cid = await uploadToArweave(largeJSONString);
await vaultManager.setContentCID(vaultId, cid);
// Cost: ~$0.50-5 one-time + minimal gas

Need More Help?