zyfai

Par bankrbot · skills

Générez du rendement sur n'importe quel portefeuille Ethereum sur Base, Arbitrum et Plasma. À utiliser lorsqu'un utilisateur souhaite obtenir un rendement DeFi passif sur ses fonds. Déploie un sous-compte déterministe non-custodial (Safe) lié à son EOA, active l'optimisation automatisée du rendement et lui permet de déposer/retirer à tout moment.

npx skills add https://github.com/bankrbot/skills --skill zyfai

Zyfai — Yield for Any Wallet

Transformez n'importe quel portefeuille Ethereum en compte générateur de rendement.

Ce que cela fait

Quand un utilisateur veut gagner du rendement sur ses cryptos, Zyfai crée un sous-compte déterministe (portefeuille intelligent Safe) lié à son portefeuille existant (EOA). Les fonds déposés dans ce sous-compte sont automatiquement optimisés sur les protocoles DeFi. L'utilisateur conserve le contrôle total et peut se retirer à tout moment.

┌─────────────────┐      ┌──────────────────────┐
│   User's EOA    │ ───► │  Zyfai Subaccount    │
│  (their wallet) │      │  (Safe smart wallet) │
│                 │      │                      │
│  Owns & controls│      │  • Auto-rebalancing  │
│                 │      │  • Yield optimization│
│                 │      │  • Non-custodial     │
└─────────────────┘      └──────────────────────┘

Points clés :

  • Le sous-compte est détenu par l'EOA de l'utilisateur — seul l'utilisateur peut effectuer des retraits
  • Les clés de session permettent le rééquilibrage automatisé mais ne peuvent pas retirer vers d'autres adresses
  • Même EOA = même adresse de sous-compte sur toutes les chaînes

Le flux

1. DEPLOY    →  Create a deterministic subaccount linked to user's wallet
2. SESSION   →  Enable automated yield optimization  
3. DEPOSIT   →  Send funds to subaccount (starts earning)
4. WITHDRAW  →  Pull funds back to wallet (anytime)

Prérequis

  • API Key — Obtenez-en une programmatiquement (voir ci-dessous) ou manuellement sur sdk.zyf.ai
  • Wallet Connection — Soit un fournisseur de portefeuille (navigateur) soit une gestion sécurisée des clés (serveur)
  • Node.js 18+
npm install @zyfai/sdk viem

Création de clé API programmatique (Native Agent)

Les agents peuvent créer leur propre clé API sans intervention humaine. Vous avez besoin de l'adresse du portefeuille (clé publique) de l'agent.

POST https://sdk.zyf.ai/api/sdk-api-keys/create
Content-Type: application/json

{
  "clientName": "my-agent",
  "walletAddress": "0x...",
  "email": "agent@example.com"
}

Réponse :

{
  "success": true,
  "message": "SDK API key created successfully. Store the apiKey securely - it cannot be retrieved later!",
  "data": {
    "id": "936...",
    "apiKey": "zyfai_361ad41d083c2fe.....",
    "keyPrefix": "zyfai_361ad4",
    "clientName": "my-agent",
    "ownerWalletAddress": "0x..."
  }
}

Important : Stockez la apiKey en sécurité — elle ne peut pas être récupérée ultérieurement. La clé est liée à l'adresse de portefeuille fournie.

Chaînes supportées

Chaîne ID
Arbitrum 42161
Base 8453
Plasma 9745

Important : Utilisez toujours l'adresse EOA

Lors de l'appel des méthodes SDK, passez toujours l'adresse EOA (l'adresse du portefeuille de l'utilisateur) en tant que userAddress — jamais l'adresse du sous-compte/Safe. Le SDK dérive automatiquement l'adresse du sous-compte à partir de l'EOA.

Options de connexion du portefeuille

Le SDK supporte plusieurs façons de connecter un portefeuille. Choisissez selon vos exigences de sécurité et votre contexte de déploiement.

Option 1 : Wallet Provider (Recommandée pour Browser/dApps)

Utilisez un fournisseur de portefeuille injecté comme MetaMask. La clé privée ne quitte jamais le portefeuille de l'utilisateur.

import { ZyfaiSDK } from "@zyfai/sdk";

const sdk = new ZyfaiSDK({ apiKey: "your-api-key", referralSource: "openclaw-skill" });

// Connect using injected wallet provider (MetaMask, WalletConnect, etc.)
await sdk.connectAccount(window.ethereum, 8453);

Sécurité : La clé privée reste dans le portefeuille de l'utilisateur. Le SDK demande uniquement des signatures quand c'est nécessaire.

Option 2 : Viem WalletClient (Recommandée pour les agents serveur)

Utilisez un WalletClient viem pré-configuré. C'est l'approche recommandée pour les agents côté serveur car elle permet l'intégration avec des solutions de gestion sécurisée des clés.

import { ZyfaiSDK } from "@zyfai/sdk";
import { createWalletClient, http } from "viem";
import { base } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";

// Create wallet client with your preferred key management
// Option A: From environment variable (simple but requires secure env management)
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);

// Option B: From KMS (AWS, GCP, etc.) - recommended for production
// const account = await getAccountFromKMS();

// Option C: From Wallet-as-a-Service (Turnkey, Privy, etc.)
// const account = await turnkeyClient.getAccount();

const walletClient = createWalletClient({
  account,
  chain: base,
  transport: http(),
});

const sdk = new ZyfaiSDK({ apiKey: "your-api-key", referralSource: "openclaw-skill" });

// Connect using the WalletClient
await sdk.connectAccount(walletClient, 8453);

Sécurité : L'abstraction WalletClient vous permet d'intégrer avec des solutions de gestion sécurisée des clés telles que :

  • AWS KMS / GCP Cloud KMS — Stockage des clés sauvegardé par matériel
  • Turnkey / Privy / Dynamic — Fournisseurs Wallet-as-a-Service
  • Hardware wallets — Via WalletConnect ou similaire

Option 3 : Private Key String (Développement uniquement)

Utilisation directe de la clé privée.

import { ZyfaiSDK } from "@zyfai/sdk";

const sdk = new ZyfaiSDK({ apiKey: "your-api-key", referralSource: "openclaw-skill" });

// WARNING: Only use for development. Never hardcode private keys in production.
await sdk.connectAccount(process.env.PRIVATE_KEY, 8453);

Avertissement de sécurité : Les clés privées brutes dans les variables d'environnement sont un risque de sécurité. Pour les agents autonomes en production, utilisez l'Option 2 avec une solution appropriée de gestion des clés.

Comparaison de sécurité

Méthode Niveau de sécurité Cas d'usage
Wallet Provider Élevé dApps navigateur, applications orientées utilisateur
WalletClient + KMS Élevé Agents serveur en production
WalletClient + WaaS Élevé Agents serveur en production
Private Key String Bas Développement/test uniquement

Étape par étape

1. Connectez-vous à Zyfai

import { ZyfaiSDK } from "@zyfai/sdk";
import { createWalletClient, http } from "viem";
import { base } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";

const sdk = new ZyfaiSDK({ apiKey: "your-api-key", referralSource: "openclaw-skill" });

// For browser: use wallet provider
await sdk.connectAccount(window.ethereum, 8453);

// For server: use WalletClient (see Wallet Connection Options above)
const walletClient = createWalletClient({
  account: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`),
  chain: base,
  transport: http(),
});
await sdk.connectAccount(walletClient, 8453);

2. Déployez le sous-compte

const userAddress = "0x..."; // User's EOA (NOT the subaccount address!)
const chainId = 8453; // Base

// Check if subaccount exists
const wallet = await sdk.getSmartWalletAddress(userAddress, chainId);
console.log(`Subaccount: ${wallet.address}`);
console.log(`Deployed: ${wallet.isDeployed}`);

// Deploy if needed
if (!wallet.isDeployed) {
  const result = await sdk.deploySafe(userAddress, chainId, "conservative");
  console.log("Subaccount deployed:", result.safeAddress);
}

Stratégies :

  • "conservative" — Rendement stable, risque plus faible
  • "aggressive" — Rendement plus élevé, risque plus élevé

3. Activez l'optimisation du rendement

await sdk.createSessionKey(userAddress, chainId);

// Always verify the session key was activated
const user = await sdk.getUserDetails();
if (!user.hasActiveSessionKey) {
  // Session key not active — retry the process
  console.log("Session key not active, retrying...");
  await sdk.createSessionKey(userAddress, chainId);

  // Verify again
  const userRetry = await sdk.getUserDetails();
  if (!userRetry.hasActiveSessionKey) {
    throw new Error("Session key activation failed after retry. Contact support.");
  }
}
console.log("Session key active:", user.hasActiveSessionKey);

Cela permet à Zyfai de rééquilibrer les fonds automatiquement. Les clés de session ne peuvent pas se retirer vers des adresses arbitraires — elles ne peuvent que optimiser au sein du protocole.

Important : Vérifiez toujours que la clé de session est active en vérifiant getUserDetails().hasActiveSessionKey après avoir appelé createSessionKey. Si elle retourne false, réessayez le processus. Une clé de session doit être active pour que l'optimisation du rendement automatisée fonctionne.

4. Déposez les fonds

// Deposit 10 USDC (6 decimals) - default asset
await sdk.depositFunds(userAddress, chainId, "10000000");

// Deposit 0.5 WETH (18 decimals)
// IMPORTANT: User must have WETH, not ETH. Wrap ETH to WETH first if needed.
await sdk.depositFunds(userAddress, chainId, "500000000000000000", "WETH");

Les fonds passent de EOA -> Sous-compte et commencent à générer du rendement immédiatement.

5. Retirez les fonds

// Withdraw all USDC (default)
await sdk.withdrawFunds(userAddress, chainId);

// Partial USDC withdrawal (5 USDC)
await sdk.withdrawFunds(userAddress, chainId, "5000000");

// Withdraw all WETH
await sdk.withdrawFunds(userAddress, chainId, undefined, "WETH");

Les fonds retournent à l'EOA de l'utilisateur. Les retraits sont traités de manière asynchrone.

6. Déconnectez-vous

await sdk.disconnectAccount();

Exemple complet

import { ZyfaiSDK } from "@zyfai/sdk";
import { createWalletClient, http } from "viem";
import { base } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";

async function startEarningYield(userAddress: string) {
  const sdk = new ZyfaiSDK({ apiKey: process.env.ZYFAI_API_KEY! });
  const chainId = 8453; // Base

  // Connect using WalletClient (recommended for server agents)
  const walletClient = createWalletClient({
    account: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`),
    chain: base,
    transport: http(),
  });
  await sdk.connectAccount(walletClient, chainId);

  // Deploy subaccount if needed (always pass EOA as userAddress)
  const wallet = await sdk.getSmartWalletAddress(userAddress, chainId);
  if (!wallet.isDeployed) {
    await sdk.deploySafe(userAddress, chainId, "conservative");
    console.log("Subaccount created:", wallet.address);
  }

  // Enable automated optimization
  await sdk.createSessionKey(userAddress, chainId);

  // Verify session key is active
  const user = await sdk.getUserDetails();
  if (!user.hasActiveSessionKey) {
    console.log("Session key not active, retrying...");
    await sdk.createSessionKey(userAddress, chainId);
    const userRetry = await sdk.getUserDetails();
    if (!userRetry.hasActiveSessionKey) {
      throw new Error("Session key activation failed. Contact support.");
    }
  }

  // Deposit 100 USDC
  await sdk.depositFunds(userAddress, chainId, "100000000");
  console.log("Deposited! Now earning yield.");

  await sdk.disconnectAccount();
}

async function withdrawYield(userAddress: string, amount?: string) {
  const sdk = new ZyfaiSDK({ apiKey: process.env.ZYFAI_API_KEY! });
  const chainId = 8453; // Base

  // Connect using WalletClient
  const walletClient = createWalletClient({
    account: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`),
    chain: base,
    transport: http(),
  });
  await sdk.connectAccount(walletClient, chainId);

  // Withdraw funds (pass EOA as userAddress)
  if (amount) {
    // Partial withdrawal
    await sdk.withdrawFunds(userAddress, chainId, amount);
    console.log(`Withdrawn ${amount} (6 decimals) to EOA`);
  } else {
    // Full withdrawal
    await sdk.withdrawFunds(userAddress, chainId);
    console.log("Withdrawn all funds to EOA");
  }

  await sdk.disconnectAccount();
}

Référence API

Méthode Paramètres Description
connectAccount (walletClientOrProvider, chainId) Authentifiez-vous avec Zyfai
getSmartWalletAddress (userAddress, chainId) Obtenez l'adresse du sous-compte et le statut
deploySafe (userAddress, chainId, strategy) Créez un sous-compte
createSessionKey (userAddress, chainId) Activez l'optimisation automatique
depositFunds (userAddress, chainId, amount, asset?) Déposez USDC ou WETH
withdrawFunds (userAddress, chainId, amount?, assetType?) Retirez USDC ou WETH
getPositions (userAddress, chainId?) Obtenez les positions DeFi actives
getAvailableProtocols (chainId) Obtenez les protocoles et pools disponibles
getAPYPerStrategy (crossChain?, days?, strategy?, chainId?, tokenSymbol?) Obtenez l'APY par stratégie et token
getUserDetails () Obtenez les détails de l'utilisateur authentifié
getOnchainEarnings (walletAddress) Obtenez les données de gains
updateUserProfile (params) Mettez à jour la stratégie, protocoles, splitting, paramètres cross-chain
registerAgentOnIdentityRegistry (smartWallet, chainId) Enregistrez l'agent sur ERC-8004 Identity Registry
disconnectAccount () Terminez la session

Note : Toutes les méthodes qui acceptent userAddress attendent l'adresse EOA, pas l'adresse du sous-compte/Safe.

Méthodes de données

getPositions

Obtenez toutes les positions DeFi actives d'un utilisateur sur les protocoles. Filtrez éventuellement par chaîne.

Paramètres :

Paramètre Type Requis Description
userAddress string Oui Adresse EOA de l'utilisateur
chainId SupportedChainId Non Optionnel : Filtrer par ID de chaîne spécifique

Exemple :

// Get all positions across all chains
const positions = await sdk.getPositions("0xUser...");

// Get positions on Arbitrum only
const arbPositions = await sdk.getPositions("0xUser...", 42161);

Retourne :

interface PositionsResponse {
  success: boolean;
  userAddress: string;
  positions: Position[];
}

getAvailableProtocols

Obtenez les protocoles DeFi disponibles et les pools pour une chaîne spécifique avec les données d'APY.

const protocols = await sdk.getAvailableProtocols(42161); // Arbitrum

protocols.protocols.forEach((protocol) => {
  console.log(`${protocol.name} (ID: ${protocol.id})`);
  if (protocol.pools) {
    protocol.pools.forEach((pool) => {
      console.log(`  Pool: ${pool.name} - APY: ${pool.apy || "N/A"}%`);
    });
  }
});

Retourne :

interface ProtocolsResponse {
  success: boolean;
  chainId: SupportedChainId;
  protocols: Protocol[];
}

getUserDetails

Obtenez les détails actuels de l'utilisateur authentifié, y compris le portefeuille intelligent, les chaînes, les protocoles et les paramètres. Nécessite l'authentification SIWE.

await sdk.connectAccount(walletClient, chainId);
const user = await sdk.getUserDetails();

console.log("Smart Wallet:", user.smartWallet);
console.log("Chains:", user.chains);
console.log("Has Active Session:", user.hasActiveSessionKey);

Retourne UpdateUserProfileResponse (identique à updateUserProfile).

updateUserProfile

Mettez à jour les paramètres du profil de l'utilisateur authentifié, y compris la stratégie, les protocoles, le splitting et les options cross-chain. Nécessite l'authentification SIWE.

sdk.updateUserProfile(params: UpdateUserProfileRequest): Promise<UpdateUserProfileResponse>

Paramètres :

interface UpdateUserProfileRequest {
  /** Investment strategy: "conservative" or "aggressive" */
  strategy?: string;
  /** Array of protocol IDs to use */
  protocols?: string[];
  /** Enable auto-selection of protocols */
  autoSelectProtocols?: boolean;
  /** Enable omni-account for cross-chain operations */
  omniAccount?: boolean;
  /** Array of chain IDs to operate on */
  chains?: number[];
  /** Enable automatic compounding (default: true) */
  autocompounding?: boolean;
  /** Custom name for your agent */
  agentName?: string;
  /** Enable cross-chain strategy execution */
  crosschainStrategy?: boolean;
  /** Enable position splitting across multiple protocols */
  splitting?: boolean;
  /** Minimum number of splits (1-4) */
  minSplits?: number;
  /** Asset to update: "usdc" (default) or "eth" */
  asset?: "USDC" | "WETH";
}

Note sur asset : Chaque asset a sa propre configuration. Utilisez asset: "WETH" pour mettre à jour les paramètres WETH séparément de USDC.

Retourne :

interface UpdateUserProfileResponse {
  success: boolean;
  smartWallet?: string;
  chains?: number[];
  strategy?: string;
  protocols?: string[];
  autoSelectProtocols?: boolean;
  omniAccount?: boolean;
  autocompounding?: boolean;
  agentName?: string;
  crosschainStrategy?: boolean;
  executorProxy?: boolean;
  hasActiveSessionKey?: boolean;
  splitting?: boolean;
  minSplits?: number;
  customization?: Record<string, any>;
  asset?: "USDC" | "WETH";
}

Exemples :

// Update strategy from conservative to aggressive
await sdk.updateUserProfile({
  strategy: "aggressive",
});

// Configure specific protocols
const protocolsResponse = await sdk.getAvailableProtocols(8453);
const selectedProtocols = protocolsResponse.protocols
  .filter(p => ["Aave", "Compound", "Moonwell"].includes(p.name))
  .map(p => p.id);

await sdk.updateUserProfile({
  protocols: selectedProtocols,
});

// Enable position splitting (distribute across multiple protocols)
await sdk.updateUserProfile({
  splitting: true,
  minSplits: 3, // Split across at least 3 protocols
});

// Verify changes
const userDetails = await sdk.getUserDetails();
console.log("Strategy:", userDetails.strategy);
console.log("Splitting:", userDetails.splitting);

Stratégies cross-chain : N'activez cross-chain que quand l'utilisateur le demande explicitement. Pour que cross-chain fonctionne, les deux crosschainStrategy et omniAccount doivent être définis sur true. N'activez jamais les paramètres cross-chain par défaut.

// Enable cross-chain ONLY when explicitly requested by the user
await sdk.updateUserProfile({
  crosschainStrategy: true,
  omniAccount: true,
});

// Now funds can be rebalanced across configured chains
const user = await sdk.getUserDetails();
console.log("Operating on chains:", user.chains);

Notes :

  • Stratégie : Peut être modifiée à tout moment. Le rééquilibrage ultérieur utilise la nouvelle stratégie active.
  • Protocoles : Utilisez getAvailableProtocols(chainId) pour obtenir les IDs de protocole valides avant la mise à jour.
  • Smart Splitting (minSplits = 1) : Mode par défaut. Pour maximiser les rendements, les fonds sont automatiquement répartis sur plusieurs pools DeFi — mais uniquement quand c'est bénéfique. Le système décide intelligemment quand le splitting est avantageux en fonction des conditions actuelles du marché et des opportunités. Les fonds peuvent ne pas se diviser si aucune opportunité n'existe.
  • Forced Splitting (minSplits > 1) : Quand minSplits est défini sur 2, 3 ou 4, les fonds sont toujours répartis sur au moins ce nombre de pools pour une meilleure diversification des risques (jusqu'à 4 pools DeFi). Cela garantit que vos fonds seront divisés indépendamment des conditions du marché.
  • Cross-chain : Nécessite à la fois crosschainStrategy: true ET omniAccount: true. Activez-le uniquement quand l'utilisateur demande explicitement l'optimisation du rendement cross-chain. Les chaînes sont configurées lors de la configuration initiale et ne peuvent pas être modifiées via cette méthode.
  • Auto-compounding : Activé par défaut. Quand true, les rendements sont réinvestis automatiquement.
  • L'adresse du portefeuille intelligent, les chaînes et executorProxy ne peuvent pas être mises à jour via cette méthode.

getAPYPerStrategy

Obtenez l'APY global par type de stratégie, période, chaîne et token. Utilisez ceci pour comparer les rendements attendus entre les stratégies avant le déploiement.

Paramètres :

Paramètre Type Requis Description
crossChain boolean Non Si true, retourne l'APY pour les stratégies cross-chain; si false, single-chain (défaut : false)
days number Non Période sur laquelle l'APY est calculée : 7, 15, 30, 60 (défaut : 7)
strategy string Non Profil de risque de la stratégie : "conservative" ou "aggressive" (défaut : "conservative")
chainId number Non Filtrer par ID de chaîne spécifique (par exemple, 8453 pour Base)
tokenSymbol string Non Filtrer par token : "USDC" ou "WETH"

Exemple :

// Get 7-day APY for USDC conservative strategy
const usdcApy = await sdk.getAPYPerStrategy(false, 7, "conservative", undefined, "USDC");
console.log("USDC APY:", usdcApy.data);

// Get 30-day APY for WETH aggressive strategy on Base
const wethApy = await sdk.getAPYPerStrategy(false, 30, "aggressive", 8453, "WETH");
console.log("WETH APY on Base:", wethApy.data);

// Compare strategies
const conservative = await sdk.getAPYPerStrategy(false, 30, "conservative");
const aggressive = await sdk.getAPYPerStrategy(false, 30, "aggressive");
console.log(`Conservative 30d APY: ${conservative.data[0]?.average_apy}%`);
console.log(`Aggressive 30d APY: ${aggressive.data[0]?.average_apy}%`);

Retourne :

interface APYPerStrategyResponse {
  success: boolean;
  count: number;
  data: APYPerStrategy[];
}

interface APYPerStrategy {
  id: string;
  timestamp: string;
  amount: number;
  fee_threshold: number;
  days: number;
  chain_id: number;
  is_cross_chain: boolean;
  average_apy: number;
  average_apy_with_rzfi: number;
  total_rebalances: number;
  created_at: string;
  strategy: string;
  token_symbol?: string;
  average_apy_with_fee: number;
  average_apy_with_rzfi_with_fee: number;
  average_apy_without_fee?: number;
  average_apy_with_rzfi_without_fee?: number;
  events_average_apy?: Record<string, number>;
}

getOnchainEarnings

Obtenez les gains on-chain pour un portefeuille avec décomposition par token (USDC, WETH).

const earnings = await sdk.getOnchainEarnings(smartWalletAddress);

console.log("Total earnings by token:", earnings.data.totalEarningsByToken);
// { "USDC": 150.50, "WETH": 0.05 }

console.log("USDC earnings:", earnings.data.totalEarningsByToken["USDC"]);
console.log("WETH earnings:", earnings.data.totalEarningsByToken["WETH"]);

Retourne :

// TokenEarnings is a record of token symbols to amounts
type TokenEarnings = Record<string, number>;  // e.g., { "USDC": 100.5, "WETH": 0.025 }

interface OnchainEarningsResponse {
  success: boolean;
  data: {
    walletAddress: string;
    totalEarningsByToken: TokenEarnings;
    lifetimeEarningsByToken: TokenEarnings;
    currentEarningsByChain: Record<string, TokenEarnings>;
    unrealizedEarningsByChain: Record<string, TokenEarnings>;
    lastCheckTimestamp?: string;
  };
}

registerAgentOnIdentityRegistry (ERC-8004)

Enregistrez votre agent déployé Zyfai sur l'Identity Registry en suivant la norme ERC-8004. Ceci est utilisé pour l'enregistrement d'agent OpenClaw. La méthode récupère un tokenUri contenant les métadonnées de l'agent stockées sur IPFS, puis l'enregistre on-chain.

Chaînes supportées :

Chaîne ID de chaîne
Base 8453
Arbitrum 42161

Paramètres :

Paramètre Type Requis Description
smartWallet string Oui L'adresse du portefeuille intelligent Zyfai déployé à enregistrer en tant qu'agent
chainId SupportedChainId Oui ID de chaîne (seulement 8453 ou 42161)

Exemple :

const sdk = new ZyfaiSDK({ apiKey: "your-api-key" });
await sdk.connectAccount(walletClient, 8453);

// Get smart wallet address
const walletInfo = await sdk.getSmartWalletAddress(userAddress, 8453);
const smartWallet = walletInfo.address;

// Register agent on Identity Registry
const result = await sdk.registerAgentOnIdentityRegistry(smartWallet, 8453);

console.log("Registration successful:");
console.log("  Tx Hash:", result.txHash);
console.log("  Chain ID:", result.chainId);
console.log("  Smart Wallet:", result.smartWallet);

Retourne :

interface RegisterAgentResponse {
  success: boolean;
  txHash: string;
  chainId: number;
  smartWallet: string;
}

Comment ça fonctionne :

  1. Récupère un tokenUri depuis l'API Zyfai (métadonnées d'agent stockées sur IPFS)
  2. Encode l'appel register(tokenUri) pour le contrat Identity Registry
  3. Envoie la transaction à partir du portefeuille connecté
  4. Attend la confirmation on-chain

Sécurité

  • Non-custodial — L'EOA de l'utilisateur possède le sous-compte
  • Les clés de session sont limitées — Peuvent rééquilibrer, ne peuvent pas se retirer ailleurs
  • Déterministe — Même EOA = même sous-compte sur chaque chaîne
  • Gestion flexible des clés — Utilisez des fournisseurs de portefeuille, WalletClients ou intégrations KMS

Bonnes pratiques de gestion des clés

Pour les agents autonomes en production, nous recommandons :

  1. Utilisez un WalletClient avec une source de clé sécurisée (pas les clés privées brutes)
  2. Intégrez avec KMS (AWS KMS, GCP Cloud KMS) pour le stockage des clés sauvegardé par matériel
  3. Considérez les fournisseurs Wallet-as-a-Service comme Turnkey, Privy ou Dynamic
  4. Ne codez jamais en dur les clés privées dans le code source
  5. Effectuez une rotation des clés périodiquement et mettez en place des procédures de révocation des clés

Dépannage

Décalage d'adresse de sous-compte entre chaînes

L'adresse du sous-compte doit être identique sur toutes les chaînes pour le même EOA. Si vous voyez des adresses différentes :

// Check addresses on both chains
const baseWallet = await sdk.getSmartWalletAddress(userAddress, 8453);
const arbWallet = await sdk.getSmartWalletAddress(userAddress, 42161);

if (baseWallet.address !== arbWallet.address) {
  console.error("Address mismatch! Contact support.");
}

Si les adresses ne correspondent pas :

  1. Essayez de redéployer sur la chaîne affectée
  2. Si le problème persiste, contactez l'assistance sur Telegram : @paul_zyfai

Erreur « Deposit address not found »

Cela signifie que le portefeuille n'est pas enregistré dans le backend. Solution :

  1. Appelez deploySafe() d'abord — même si le Safe est déjà déployé on-chain, cela l'enregistre auprès du backend
  2. Réessayez ensuite createSessionKey()

Erreur « Invalid signature »

Cela signifie généralement :

  • Le portefeuille/signataire ne correspond pas à l'EOA que vous passez
  • L'adresse Safe on-chain ne correspond pas à ce que le SDK attend

Vérifiez que vous utilisez le portefeuille correct pour l'EOA.

Ressources

Licence

MIT License

Copyright (c) 2026 Zyfai

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Skills similaires