@ember-finance/sdk
v1.2.4
Published
Ember Protocol SDK
Downloads
2,697
Readme
Ember Protocol SDK
A comprehensive TypeScript SDK for interacting with the Ember Protocol on both SUI and EVM-compatible blockchains. This SDK provides a complete set of tools for managing vaults, handling user operations, and administering the protocol.
Overview
The Ember Protocol SDK is a TypeScript library that enables developers to interact with the Ember Protocol's vault system on both SUI and EVM-compatible blockchains. The protocol allows users to deposit assets into vaults, receive shares, and participate in yield-generating strategies.
Supported Chains
- SUI - Full support for SUI blockchain
- EVM - Support for Ethereum and EVM-compatible chains (using ethers.js v6)
- EVM vaults implement the ERC-4626 tokenized vault standard
- The vault contract itself is the share token (ERC20)
Architecture
The SDK is built around several key classes:
- EmberVaults: Main entry point for vault interactions (supports both SUI and EVM)
- AdminCalls: Administrative functions for protocol management
- UserCalls: User-facing operations for deposits and withdrawals
- OperatorCalls: Operator functions for vault management
- VaultAdminCalls: Vault-specific administrative functions
- TxBuilder: Transaction building utilities
Installation
npm install @ember-finance/sdkor
yarn add @ember-finance/sdkUsage
SUI Chain - User Deposit Example
import { EmberVaults } from "@ember-finance/sdk";
import { SuiClient, Ed25519Keypair } from "@mysten/sui.js";
// Setup SUI client and signer
const suiClient = new SuiClient({ url: "https://fullnode.mainnet.sui.io" });
const keypair = Ed25519Keypair.fromSecretKey(privateKeyBytes);
// Initialize EmberVaults for SUI
const ember = new EmberVaults({
chainType: "sui",
network: "mainnet",
suiClient,
signer: keypair,
environment: "prod" // "prod" | "staging" | "dev"
});
// Fetch deployment configuration from API
await ember.init();
// Get vault information
const vaultId = ember.parser.getVaultIdFromName("USDC Vault");
// Deposit assets into the vault
const depositAmount = "1000000"; // 1 USDC (6 decimals)
const result = await ember.user.depositAsset(vaultId, depositAmount);
console.log("Deposit successful:", result);EVM Chain - User Deposit Example (ERC-4626)
The EVM vaults implement the ERC-4626 tokenized vault standard. The vault contract itself is the share token, so there's no separate receipt token.
Traditional Approach (Two Transactions)
import { EmberVaults } from "@ember-finance/sdk";
import { ethers } from "ethers";
// Setup ethers provider and signer
const provider = new ethers.JsonRpcProvider("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY");
const signer = new ethers.Wallet(privateKey, provider);
// EVM deployment configuration (can be fetched from API or provided directly)
const deployment = {
network: "ethereum",
chainId: "1",
contracts: {
protocolConfig: {
proxyAddress: "0x...",
// ... other config
},
vaults: {
"USDC Vault": {
proxyAddress: "0x...",
baseToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
// ... other config
}
},
receiptTokens: {
// Note: For ERC-4626, the vault is the share token
}
}
};
// Initialize EmberVaults for EVM
const ember = new EmberVaults({
chainType: "evm",
signer,
provider,
deployment,
environment: "prod"
});
// Or fetch deployment from API
// await ember.init();
const vaultAddress = deployment.contracts.vaults["USDC Vault"].proxyAddress;
const underlyingAsset = deployment.contracts.vaults["USDC Vault"].baseToken;
const depositAmount = "1000000"; // 1 USDC (6 decimals)
// Step 1: Approve token spending (required for EVM)
await ember.user.approveTokenMax(underlyingAsset, vaultAddress);
// Step 2: Deposit assets (ERC-4626 standard: deposit(assets, receiver))
// Receiver defaults to caller
const result = await ember.user.deposit(vaultAddress, depositAmount);
console.log("Deposit successful:", result);
// Optional: Wait for receipt and get events
const resultWithEvents = await ember.user.deposit(
vaultAddress,
depositAmount,
{ waitForReceipt: true }
);
console.log("Events:", resultWithEvents.events);New Approach: Single Transaction with EIP-2612 Permit (Recommended)
The new depositWithPermit and mintWithPermit methods allow depositing in a single
transaction without requiring a separate approval transaction. This uses EIP-2612 permit
signatures.
import { EmberVaults, signPermitSimple } from "@ember-finance/sdk";
import { ethers } from "ethers";
// Setup (same as above)
const provider = new ethers.JsonRpcProvider("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY");
const signer = new ethers.Wallet(privateKey, provider);
const ember = new EmberVaults({
chainType: "evm",
signer,
provider,
deployment,
environment: "prod"
});
const vaultAddress = deployment.contracts.vaults["USDC Vault"].proxyAddress;
const underlyingAsset = deployment.contracts.vaults["USDC Vault"].baseToken;
const depositAmount = "1000000"; // 1 USDC (6 decimals)
// Generate permit signature (off-chain, no gas cost)
const permitSig = await signPermitSimple(
signer,
underlyingAsset,
"USD Coin", // Token name (must match token's EIP-2612 name)
vaultAddress,
depositAmount
);
// Deposit with permit in a SINGLE transaction (no separate approval needed!)
const result = await ember.user.depositWithPermit(
vaultAddress,
depositAmount,
permitSig
);
console.log("Deposit successful:", result);EVM - Deposit to a Different Receiver
// Deposit, with shares going to a different address
const result = await ember.user.deposit(
vaultAddress,
depositAmount,
{ receiver: "0xRecipientAddress..." }
);EVM - Mint Specific Shares (ERC-4626)
Traditional Approach (Requires Approval)
// Mint a specific number of shares (vault will pull required assets)
const sharesToMint = "1000000000000000000"; // 1e18 shares
// Must approve first
await ember.user.approveTokenMax(underlyingAsset, vaultAddress);
await ember.user.mint(vaultAddress, sharesToMint);
// Mint to a different receiver
await ember.user.mint(vaultAddress, sharesToMint, {
receiver: "0xRecipientAddress..."
});Single Transaction with Permit
import { signPermitSimple } from "@ember-finance/sdk";
const sharesToMint = "1000000000000000000"; // 1e18 shares
// Generate permit signature for a high amount (vault will pull exact amount needed)
const permitSig = await signPermitSimple(
signer,
underlyingAsset,
"USD Coin",
vaultAddress,
"115792089237316195423570985008687907853269984665640564039457584007913129639935" // max uint256
);
// Mint with permit in single transaction
await ember.user.mintWithPermit(vaultAddress, sharesToMint, permitSig);
// Mint to a different receiver
await ember.user.mintWithPermit(vaultAddress, sharesToMint, permitSig, {
receiver: "0xRecipientAddress..."
});EVM - Redeem Shares (Initiate Withdrawal)
// Redeem shares to initiate a withdrawal request
// Note: Withdrawal requests are processed by operators, not immediate
const shares = "500000000000000000000"; // shares to redeem
// Redeem to self (default)
await ember.user.redeemShares(vaultAddress, shares);
// Redeem to a different receiver
await ember.user.redeemShares(vaultAddress, shares, {
receiver: "0xRecipientAddress..."
});Type-Safe Chain Access
// Check chain type at runtime
if (ember.isSui()) {
// TypeScript knows this is SUI
const suiClient = ember.suiClient;
// ... SUI-specific operations
}
if (ember.isEvm()) {
// TypeScript knows this is EVM
const provider = ember.provider;
// ... EVM-specific operations
}
// Get strongly-typed chain-specific instance
const suiEmber = ember.asSui(); // throws if not SUI
const evmEmber = ember.asEvm(); // throws if not EVMCore Components
EmberVaults
The main entry point for interacting with the Ember Protocol:
// Common properties available for both chains
ember.chainType // "sui" | "evm"
ember.vaultsApi // VaultsApi - same for both chains
ember.api // AccountsApi - same for both chains
ember.parser // Deployment parser (chain-specific)
ember.txBuilder // Transaction builder (chain-specific)
ember.admin // Admin calls (chain-specific)
ember.operator // Operator calls (chain-specific)
ember.vaultAdmin // Vault admin calls (chain-specific)
ember.user // User calls (chain-specific)
ember.deployment // Deployment config (chain-specific)User Operations (UserCalls)
Handle user-facing vault operations:
EVM (ERC-4626):
- deposit: Deposit assets and receive shares (ERC-4626 standard, requires approval)
- depositWithPermit: Deposit assets using EIP-2612 permit (single transaction, no approval needed) ✨ NEW
- mint: Mint specific shares by depositing required assets (ERC-4626 standard, requires approval)
- mintWithPermit: Mint shares using EIP-2612 permit (single transaction, no approval needed) ✨ NEW
- redeemShares: Redeem shares to initiate withdrawal request
- cancelPendingWithdrawalRequest: Cancel pending withdrawal requests
- approveToken: Approve token spending
- approveTokenMax: Approve maximum token spending
Permit Utilities (EVM): ✨ NEW
- signPermitSimple: Generate EIP-2612 permit signature with automatic nonce and deadline
- signPermit: Generate EIP-2612 permit signature with custom parameters
- getPermitNonce: Get current permit nonce for a user
SUI:
- depositAsset: Deposit assets into a vault
- mintShares: Mint vault shares with specific amount
- redeemShares: Redeem shares for underlying assets
- cancelPendingWithdrawalRequest: Cancel pending withdrawal requests
Admin Functions (AdminCalls)
Protocol-level administrative functions:
- updateMaxFeePercentage: Update protocol fee limits
- pauseNonAdminOperations: Emergency protocol controls
- updatePlatformFeeRecipient: Update fee recipient
- setBlacklistedAccount: Manage blacklisted accounts
- updateVaultAdmin: Update vault admin address
Operator Functions (OperatorCalls)
Vault operator management functions:
- collectPlatformFee: Collect accumulated fees
- processWithdrawalRequests: Process pending withdrawals
- updateVaultRate: Update vault exchange rates (rate manager role)
- withdrawFromVaultWithoutRedeemingShares: Withdraw for strategy execution
Vault Admin Functions (VaultAdminCalls)
Vault-specific administrative controls (called via ProtocolConfig on EVM):
- updateVaultMinWithdrawableShares: Configure minimum withdrawal amounts
- setVaultSubAccount: Manage vault sub-accounts
- updateVaultOperator: Change vault operators
- updateVaultRateManager: Change rate manager
- setVaultPausedStatus: Pause/unpause vault operations
- updateVaultFeePercentage: Update vault fee percentage
- updateVaultMaxTVL: Update maximum TVL
- updateVaultRateUpdateInterval: Update rate update interval
- updateVaultName: Update vault name
EIP-2612 Permit Support (EVM) ✨ NEW
The Ember vaults now support EIP-2612 permit signatures, allowing users to deposit or mint shares in a single transaction without requiring a separate approval transaction. This significantly improves the user experience by:
- Reducing gas costs (one transaction instead of two)
- Eliminating the need to wait for approval transaction confirmation
- Providing a smoother, faster deposit flow
How Permit Works
EIP-2612 allows users to sign an off-chain message (no gas cost) that authorizes the vault to spend their tokens. This signature is then included in the deposit/mint transaction, which handles both the approval and the deposit atomically.
Using Permit with the SDK
import { EmberVaults, signPermitSimple } from "@ember-finance/sdk";
// 1. Generate permit signature (off-chain, no gas)
const permitSig = await signPermitSimple(
signer,
tokenAddress,
"USD Coin", // Token name (must match EIP-2612 name)
vaultAddress,
amount
);
// 2. Deposit with permit (single transaction)
await ember.user.depositWithPermit(vaultAddress, amount, permitSig);Advanced Permit Usage
For more control over the permit parameters:
import { signPermit, getPermitNonce } from "@ember-finance/sdk";
// Get current nonce for the user
const nonce = await getPermitNonce(tokenAddress, userAddress, provider);
// Set custom deadline (e.g., 24 hours from now)
const deadline = BigInt(Math.floor(Date.now() / 1000) + 86400);
// Get chain ID
const network = await provider.getNetwork();
const chainId = network.chainId;
// Sign permit with custom parameters
const permitSig = await signPermit(
signer,
tokenAddress,
"USD Coin",
vaultAddress,
amount,
deadline,
nonce,
chainId
);
// Use the permit
await ember.user.depositWithPermit(vaultAddress, amount, permitSig);Important Notes
- Token Support: The underlying token must support EIP-2612 permit. Most modern tokens (USDC, DAI, etc.) support this standard.
- Token Name: The token name passed to
signPermitmust match the token's EIP-2612 domain name exactly. - Deadline: Permit signatures have a deadline. After the deadline, the signature becomes invalid.
- Nonce: Each permit signature uses a nonce. Once used, the nonce increments and the signature cannot be reused.
ERC-4626 Compatibility (EVM)
The EVM vaults are fully ERC-4626 compliant:
| ERC-4626 Method | SDK Method | Notes |
| ----------------------------------- | ------------------------------------------ | --------------------------------- |
| asset() | - | Returns underlying asset address |
| deposit(assets, receiver) | user.deposit(vault, assets, {receiver?}) | Deposit assets, get shares |
| mint(shares, receiver) | user.mint(vault, shares, {receiver?}) | Mint shares by depositing assets |
| withdraw(assets, receiver, owner) | N/A | Not supported, use redeemShares |
| redeem(shares, receiver, owner) | N/A | Not supported, use redeemShares |
| totalAssets() | - | Read via contract |
| convertToShares(assets) | - | Read via contract |
| convertToAssets(shares) | - | Read via contract |
| previewDeposit(assets) | - | Read via contract |
| previewMint(shares) | - | Read via contract |
Note: Standard ERC-4626 withdraw and redeem are not supported due to the vault's async
withdrawal mechanism. Use redeemShares to initiate a withdrawal request, which will be
processed by vault operators.
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Built with ❤️ by the Ember Protocol team
