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
apiKeyen 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().hasActiveSessionKeyaprès avoir appelécreateSessionKey. Si elle retournefalse, 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
crosschainStrategyetomniAccountdoivent être définis surtrue. 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
minSplitsest 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: trueETomniAccount: 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
executorProxyne 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 :
- Récupère un
tokenUridepuis l'API Zyfai (métadonnées d'agent stockées sur IPFS) - Encode l'appel
register(tokenUri)pour le contrat Identity Registry - Envoie la transaction à partir du portefeuille connecté
- 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 :
- Utilisez un WalletClient avec une source de clé sécurisée (pas les clés privées brutes)
- Intégrez avec KMS (AWS KMS, GCP Cloud KMS) pour le stockage des clés sauvegardé par matériel
- Considérez les fournisseurs Wallet-as-a-Service comme Turnkey, Privy ou Dynamic
- Ne codez jamais en dur les clés privées dans le code source
- 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 :
- Essayez de redéployer sur la chaîne affectée
- 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 :
- Appelez
deploySafe()d'abord — même si le Safe est déjà déployé on-chain, cela l'enregistre auprès du backend - 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
- Obtenir une clé API : sdk.zyf.ai ou programmatiquement via
POST /api/sdk-api-keys/create - Docs : docs.zyf.ai
- Démo : github.com/ondefy/zyfai-sdk-demo
- MCP Server : mcp.zyf.ai — À utiliser avec Claude ou d'autres agents compatibles MCP
- Enregistrement d'agent : zyf.ai/.well-known/agent-registration.json
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.