@ember-finance/sdk 1.1.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { Signer, Provider } from "ethers";
2
2
  import { EVMOnChainCalls } from "./onchain-calls";
3
- import { IEvmDeployment, IUserCallOptions, IEvmCallOptions, EvmOnChainCallResponse } from "../interfaces";
3
+ import { IEvmDeployment, IUserCallOptions, IEvmCallOptions, EvmOnChainCallResponse, IPermitSignature } from "../interfaces";
4
4
  import { NumStr } from "../../common/types";
5
5
  /**
6
6
  * User Calls for Ember Protocol on EVM (ERC-4626 Compatible)
@@ -10,7 +10,9 @@ import { NumStr } from "../../common/types";
10
10
  *
11
11
  * Users can:
12
12
  * - deposit: Deposit assets and receive shares (ERC-4626)
13
+ * - depositWithPermit: Deposit assets using EIP-2612 permit (no separate approval needed)
13
14
  * - mint: Mint a specific number of shares by depositing assets (ERC-4626)
15
+ * - mintWithPermit: Mint shares using EIP-2612 permit (no separate approval needed)
14
16
  * - redeemShares: Initiate a withdrawal request by redeeming shares
15
17
  * - cancelPendingWithdrawalRequest: Cancel a pending withdrawal
16
18
  *
@@ -28,12 +30,14 @@ import { NumStr } from "../../common/types";
28
30
  *
29
31
  * const userCalls = new EVMUserCalls(deployment, signer, provider);
30
32
  *
31
- * // Approve token spending first
33
+ * // Traditional approach: Approve token spending first, then deposit
32
34
  * await userCalls.approveToken(underlyingAsset, vaultAddress, amount);
33
- *
34
- * // Deposit assets (receiver defaults to caller)
35
35
  * await userCalls.deposit(vaultAddress, amount);
36
36
  *
37
+ * // New approach: Use permit to deposit in single transaction (no approval needed)
38
+ * const permitSig = await signPermit(signer, tokenAddress, vaultAddress, amount, deadline);
39
+ * await userCalls.depositWithPermit(vaultAddress, amount, permitSig);
40
+ *
37
41
  * // Deposit assets to a different receiver
38
42
  * await userCalls.deposit(vaultAddress, amount, { receiver: otherAddress });
39
43
  *
@@ -58,6 +62,39 @@ export declare class EVMUserCalls extends EVMOnChainCalls {
58
62
  * @returns EvmOnChainCallResponse
59
63
  */
60
64
  deposit(vaultAddress: string, assets: NumStr, options?: IUserCallOptions): Promise<EvmOnChainCallResponse>;
65
+ /**
66
+ * Deposit assets into a vault using EIP-2612 permit (no separate approval needed)
67
+ *
68
+ * This method allows depositing in a single transaction by including a permit signature.
69
+ * The permit signature authorizes the vault to spend the underlying asset without requiring
70
+ * a separate approve transaction.
71
+ *
72
+ * @param vaultAddress The address of the vault
73
+ * @param assets The amount of assets to deposit
74
+ * @param permitSignature The EIP-2612 permit signature components
75
+ * @param options Optional tx execution params (includes optional receiver, defaults to caller)
76
+ * @returns EvmOnChainCallResponse
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * // Generate permit signature (see signPermit utility)
81
+ * const permitSig = await signPermit(
82
+ * signer,
83
+ * tokenAddress,
84
+ * vaultAddress,
85
+ * amount,
86
+ * deadline
87
+ * );
88
+ *
89
+ * // Deposit with permit in single transaction
90
+ * await userCalls.depositWithPermit(
91
+ * vaultAddress,
92
+ * amount,
93
+ * permitSig
94
+ * );
95
+ * ```
96
+ */
97
+ depositWithPermit(vaultAddress: string, assets: NumStr, permitSignature: IPermitSignature, options?: IUserCallOptions): Promise<EvmOnChainCallResponse>;
61
98
  /**
62
99
  * Mint a specific number of shares by depositing assets (ERC-4626 standard)
63
100
  *
@@ -70,6 +107,39 @@ export declare class EVMUserCalls extends EVMOnChainCalls {
70
107
  * @returns EvmOnChainCallResponse
71
108
  */
72
109
  mint(vaultAddress: string, shares: NumStr, options?: IUserCallOptions): Promise<EvmOnChainCallResponse>;
110
+ /**
111
+ * Mint a specific number of shares using EIP-2612 permit (no separate approval needed)
112
+ *
113
+ * This method allows minting shares in a single transaction by including a permit signature.
114
+ * The permit signature authorizes the vault to spend the required underlying assets without
115
+ * requiring a separate approve transaction.
116
+ *
117
+ * @param vaultAddress The address of the vault
118
+ * @param shares The number of shares to mint
119
+ * @param permitSignature The EIP-2612 permit signature components
120
+ * @param options Optional tx execution params (includes optional receiver, defaults to caller)
121
+ * @returns EvmOnChainCallResponse
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * // Generate permit signature (see signPermit utility)
126
+ * const permitSig = await signPermit(
127
+ * signer,
128
+ * tokenAddress,
129
+ * vaultAddress,
130
+ * maxAmount, // Use high amount or max for mint since exact amount is calculated by vault
131
+ * deadline
132
+ * );
133
+ *
134
+ * // Mint shares with permit in single transaction
135
+ * await userCalls.mintWithPermit(
136
+ * vaultAddress,
137
+ * shares,
138
+ * permitSig
139
+ * );
140
+ * ```
141
+ */
142
+ mintWithPermit(vaultAddress: string, shares: NumStr, permitSignature: IPermitSignature, options?: IUserCallOptions): Promise<EvmOnChainCallResponse>;
73
143
  /**
74
144
  * Redeem shares to initiate a withdrawal request
75
145
  *
@@ -15,7 +15,9 @@ const EmberVault_json_1 = __importDefault(require("../../abis/EmberVault.json"))
15
15
  *
16
16
  * Users can:
17
17
  * - deposit: Deposit assets and receive shares (ERC-4626)
18
+ * - depositWithPermit: Deposit assets using EIP-2612 permit (no separate approval needed)
18
19
  * - mint: Mint a specific number of shares by depositing assets (ERC-4626)
20
+ * - mintWithPermit: Mint shares using EIP-2612 permit (no separate approval needed)
19
21
  * - redeemShares: Initiate a withdrawal request by redeeming shares
20
22
  * - cancelPendingWithdrawalRequest: Cancel a pending withdrawal
21
23
  *
@@ -33,12 +35,14 @@ const EmberVault_json_1 = __importDefault(require("../../abis/EmberVault.json"))
33
35
  *
34
36
  * const userCalls = new EVMUserCalls(deployment, signer, provider);
35
37
  *
36
- * // Approve token spending first
38
+ * // Traditional approach: Approve token spending first, then deposit
37
39
  * await userCalls.approveToken(underlyingAsset, vaultAddress, amount);
38
- *
39
- * // Deposit assets (receiver defaults to caller)
40
40
  * await userCalls.deposit(vaultAddress, amount);
41
41
  *
42
+ * // New approach: Use permit to deposit in single transaction (no approval needed)
43
+ * const permitSig = await signPermit(signer, tokenAddress, vaultAddress, amount, deadline);
44
+ * await userCalls.depositWithPermit(vaultAddress, amount, permitSig);
45
+ *
42
46
  * // Deposit assets to a different receiver
43
47
  * await userCalls.deposit(vaultAddress, amount, { receiver: otherAddress });
44
48
  *
@@ -72,6 +76,43 @@ class EVMUserCalls extends onchain_calls_1.EVMOnChainCalls {
72
76
  const txCall = this.txBuilder.deposit(vaultAddress, assets, receiver);
73
77
  return this.execCall(txCall, options);
74
78
  }
79
+ /**
80
+ * Deposit assets into a vault using EIP-2612 permit (no separate approval needed)
81
+ *
82
+ * This method allows depositing in a single transaction by including a permit signature.
83
+ * The permit signature authorizes the vault to spend the underlying asset without requiring
84
+ * a separate approve transaction.
85
+ *
86
+ * @param vaultAddress The address of the vault
87
+ * @param assets The amount of assets to deposit
88
+ * @param permitSignature The EIP-2612 permit signature components
89
+ * @param options Optional tx execution params (includes optional receiver, defaults to caller)
90
+ * @returns EvmOnChainCallResponse
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * // Generate permit signature (see signPermit utility)
95
+ * const permitSig = await signPermit(
96
+ * signer,
97
+ * tokenAddress,
98
+ * vaultAddress,
99
+ * amount,
100
+ * deadline
101
+ * );
102
+ *
103
+ * // Deposit with permit in single transaction
104
+ * await userCalls.depositWithPermit(
105
+ * vaultAddress,
106
+ * amount,
107
+ * permitSig
108
+ * );
109
+ * ```
110
+ */
111
+ async depositWithPermit(vaultAddress, assets, permitSignature, options) {
112
+ const receiver = options?.receiver ?? (await this.getWalletAddress());
113
+ const txCall = this.txBuilder.depositWithPermit(vaultAddress, assets, receiver, permitSignature);
114
+ return this.execCall(txCall, options);
115
+ }
75
116
  // ============================================
76
117
  // Mint Methods (ERC-4626)
77
118
  // ============================================
@@ -91,6 +132,43 @@ class EVMUserCalls extends onchain_calls_1.EVMOnChainCalls {
91
132
  const txCall = this.txBuilder.mint(vaultAddress, shares, receiver);
92
133
  return this.execCall(txCall, options);
93
134
  }
135
+ /**
136
+ * Mint a specific number of shares using EIP-2612 permit (no separate approval needed)
137
+ *
138
+ * This method allows minting shares in a single transaction by including a permit signature.
139
+ * The permit signature authorizes the vault to spend the required underlying assets without
140
+ * requiring a separate approve transaction.
141
+ *
142
+ * @param vaultAddress The address of the vault
143
+ * @param shares The number of shares to mint
144
+ * @param permitSignature The EIP-2612 permit signature components
145
+ * @param options Optional tx execution params (includes optional receiver, defaults to caller)
146
+ * @returns EvmOnChainCallResponse
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * // Generate permit signature (see signPermit utility)
151
+ * const permitSig = await signPermit(
152
+ * signer,
153
+ * tokenAddress,
154
+ * vaultAddress,
155
+ * maxAmount, // Use high amount or max for mint since exact amount is calculated by vault
156
+ * deadline
157
+ * );
158
+ *
159
+ * // Mint shares with permit in single transaction
160
+ * await userCalls.mintWithPermit(
161
+ * vaultAddress,
162
+ * shares,
163
+ * permitSig
164
+ * );
165
+ * ```
166
+ */
167
+ async mintWithPermit(vaultAddress, shares, permitSignature, options) {
168
+ const receiver = options?.receiver ?? (await this.getWalletAddress());
169
+ const txCall = this.txBuilder.mintWithPermit(vaultAddress, shares, receiver, permitSignature);
170
+ return this.execCall(txCall, options);
171
+ }
94
172
  // ============================================
95
173
  // Redemption Methods
96
174
  // ============================================
@@ -1 +1,2 @@
1
1
  export * from "./deployment-parser";
2
+ export * from "./permit-utils";
@@ -15,3 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./deployment-parser"), exports);
18
+ __exportStar(require("./permit-utils"), exports);
@@ -0,0 +1,112 @@
1
+ import { Signer } from "ethers";
2
+ import { IPermitSignature } from "../interfaces";
3
+ import { NumStr } from "../../common/types";
4
+ /**
5
+ * Signs an EIP-2612 permit message
6
+ *
7
+ * This creates an off-chain signature that authorizes a spender (vault) to spend
8
+ * tokens on behalf of the owner without requiring a separate approval transaction.
9
+ *
10
+ * @param signer The ethers.js signer
11
+ * @param tokenAddress The address of the ERC20 token (must support EIP-2612)
12
+ * @param tokenName The name of the token (for domain separator)
13
+ * @param spender The address authorized to spend (usually the vault address)
14
+ * @param value The amount of tokens to approve
15
+ * @param deadline The deadline timestamp (in seconds) for the permit
16
+ * @param nonce The current permit nonce for the owner (fetch from token.nonces(owner))
17
+ * @param chainId The chain ID
18
+ * @param version Optional version string for the domain separator (fetched from token if not provided)
19
+ * @returns The permit signature components
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import { signPermit } from "@ember-finance/sdk";
24
+ *
25
+ * const deadline = Math.floor(Date.now() / 1000) + 3600; // 1 hour from now
26
+ * const tokenContract = new ethers.Contract(tokenAddress, erc20Abi, provider);
27
+ * const nonce = await tokenContract.nonces(await signer.getAddress());
28
+ *
29
+ * const permitSig = await signPermit(
30
+ * signer,
31
+ * tokenAddress,
32
+ * "USD Coin", // token name
33
+ * vaultAddress,
34
+ * amount,
35
+ * BigInt(deadline),
36
+ * nonce,
37
+ * BigInt(1) // Ethereum mainnet
38
+ * );
39
+ *
40
+ * // Use with depositWithPermit
41
+ * await userCalls.depositWithPermit(vaultAddress, amount, permitSig);
42
+ * ```
43
+ */
44
+ export declare function signPermit(signer: Signer, tokenAddress: string, tokenName: string, spender: string, value: NumStr, deadline: bigint, nonce: bigint, chainId: bigint, version?: string): Promise<IPermitSignature>;
45
+ /**
46
+ * Helper function to get the permit version from an EIP-2612 token
47
+ *
48
+ * @param tokenAddress The address of the ERC20 token
49
+ * @param provider An ethers.js provider
50
+ * @returns The version string (e.g., "1", "2"), defaults to "1" if version() not implemented
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * import { getPermitVersion } from "@ember-finance/sdk";
55
+ *
56
+ * const version = await getPermitVersion(tokenAddress, provider);
57
+ * ```
58
+ */
59
+ export declare function getPermitVersion(tokenAddress: string, provider: import("ethers").Provider): Promise<string>;
60
+ /**
61
+ * Helper function to get the current nonce for a user from an EIP-2612 token
62
+ *
63
+ * @param tokenAddress The address of the ERC20 token
64
+ * @param ownerAddress The address of the token owner
65
+ * @param provider An ethers.js provider
66
+ * @returns The current nonce
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * import { getPermitNonce } from "@ember-finance/sdk";
71
+ *
72
+ * const nonce = await getPermitNonce(
73
+ * tokenAddress,
74
+ * await signer.getAddress(),
75
+ * provider
76
+ * );
77
+ * ```
78
+ */
79
+ export declare function getPermitNonce(tokenAddress: string, ownerAddress: string, provider: import("ethers").Provider): Promise<bigint>;
80
+ /**
81
+ * Helper function to create a permit signature with sensible defaults
82
+ *
83
+ * This is a convenience function that:
84
+ * - Fetches the current nonce automatically
85
+ * - Fetches the version from the token contract
86
+ * - Sets a deadline of 1 hour from now
87
+ * - Gets the chain ID from the signer
88
+ *
89
+ * @param signer The ethers.js signer (must be connected to a provider)
90
+ * @param tokenAddress The address of the ERC20 token (must support EIP-2612)
91
+ * @param tokenName The name of the token (for domain separator)
92
+ * @param spender The address authorized to spend (usually the vault address)
93
+ * @param value The amount of tokens to approve
94
+ * @returns The permit signature components
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * import { signPermitSimple } from "@ember-finance/sdk";
99
+ *
100
+ * // Simplified permit signing (fetches nonce, version, sets 1 hour deadline automatically)
101
+ * const permitSig = await signPermitSimple(
102
+ * signer,
103
+ * tokenAddress,
104
+ * "USD Coin",
105
+ * vaultAddress,
106
+ * amount
107
+ * );
108
+ *
109
+ * await userCalls.depositWithPermit(vaultAddress, amount, permitSig);
110
+ * ```
111
+ */
112
+ export declare function signPermitSimple(signer: Signer, tokenAddress: string, tokenName: string, spender: string, value: NumStr): Promise<IPermitSignature>;
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.signPermit = signPermit;
37
+ exports.getPermitVersion = getPermitVersion;
38
+ exports.getPermitNonce = getPermitNonce;
39
+ exports.signPermitSimple = signPermitSimple;
40
+ /**
41
+ * Signs an EIP-2612 permit message
42
+ *
43
+ * This creates an off-chain signature that authorizes a spender (vault) to spend
44
+ * tokens on behalf of the owner without requiring a separate approval transaction.
45
+ *
46
+ * @param signer The ethers.js signer
47
+ * @param tokenAddress The address of the ERC20 token (must support EIP-2612)
48
+ * @param tokenName The name of the token (for domain separator)
49
+ * @param spender The address authorized to spend (usually the vault address)
50
+ * @param value The amount of tokens to approve
51
+ * @param deadline The deadline timestamp (in seconds) for the permit
52
+ * @param nonce The current permit nonce for the owner (fetch from token.nonces(owner))
53
+ * @param chainId The chain ID
54
+ * @param version Optional version string for the domain separator (fetched from token if not provided)
55
+ * @returns The permit signature components
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * import { signPermit } from "@ember-finance/sdk";
60
+ *
61
+ * const deadline = Math.floor(Date.now() / 1000) + 3600; // 1 hour from now
62
+ * const tokenContract = new ethers.Contract(tokenAddress, erc20Abi, provider);
63
+ * const nonce = await tokenContract.nonces(await signer.getAddress());
64
+ *
65
+ * const permitSig = await signPermit(
66
+ * signer,
67
+ * tokenAddress,
68
+ * "USD Coin", // token name
69
+ * vaultAddress,
70
+ * amount,
71
+ * BigInt(deadline),
72
+ * nonce,
73
+ * BigInt(1) // Ethereum mainnet
74
+ * );
75
+ *
76
+ * // Use with depositWithPermit
77
+ * await userCalls.depositWithPermit(vaultAddress, amount, permitSig);
78
+ * ```
79
+ */
80
+ async function signPermit(signer, tokenAddress, tokenName, spender, value, deadline, nonce, chainId, version) {
81
+ const owner = await signer.getAddress();
82
+ // If version not provided, fetch it from the token contract
83
+ let permitVersion = version;
84
+ if (!permitVersion) {
85
+ const provider = signer.provider;
86
+ if (!provider) {
87
+ throw new Error("Signer must be connected to a provider to fetch version");
88
+ }
89
+ permitVersion = await getPermitVersion(tokenAddress, provider);
90
+ }
91
+ // EIP-2612 domain
92
+ const domain = {
93
+ name: tokenName,
94
+ version: permitVersion,
95
+ chainId: chainId,
96
+ verifyingContract: tokenAddress
97
+ };
98
+ // EIP-2612 Permit type
99
+ const types = {
100
+ Permit: [
101
+ { name: "owner", type: "address" },
102
+ { name: "spender", type: "address" },
103
+ { name: "value", type: "uint256" },
104
+ { name: "nonce", type: "uint256" },
105
+ { name: "deadline", type: "uint256" }
106
+ ]
107
+ };
108
+ // Permit message
109
+ const message = {
110
+ owner,
111
+ spender,
112
+ value: BigInt(value),
113
+ nonce,
114
+ deadline
115
+ };
116
+ // Sign the typed data
117
+ const signature = await signer.signTypedData(domain, types, message);
118
+ // Split signature into v, r, s components
119
+ const r = signature.slice(0, 66);
120
+ const s = "0x" + signature.slice(66, 130);
121
+ const v = parseInt(signature.slice(130, 132), 16);
122
+ return {
123
+ deadline,
124
+ v,
125
+ r,
126
+ s
127
+ };
128
+ }
129
+ /**
130
+ * Helper function to get the permit version from an EIP-2612 token
131
+ *
132
+ * @param tokenAddress The address of the ERC20 token
133
+ * @param provider An ethers.js provider
134
+ * @returns The version string (e.g., "1", "2"), defaults to "1" if version() not implemented
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * import { getPermitVersion } from "@ember-finance/sdk";
139
+ *
140
+ * const version = await getPermitVersion(tokenAddress, provider);
141
+ * ```
142
+ */
143
+ async function getPermitVersion(tokenAddress, provider) {
144
+ try {
145
+ const { Contract } = await Promise.resolve().then(() => __importStar(require("ethers")));
146
+ const tokenContract = new Contract(tokenAddress, ["function version() view returns (string)"], provider);
147
+ return await tokenContract.version();
148
+ }
149
+ catch (error) {
150
+ // TODO: change this to "1" when we have a token that supports version "1"
151
+ // If version() is not implemented, default to "2"
152
+ // Most EIP-2612 tokens use version "2" unless specified otherwise
153
+ return "2";
154
+ }
155
+ }
156
+ /**
157
+ * Helper function to get the current nonce for a user from an EIP-2612 token
158
+ *
159
+ * @param tokenAddress The address of the ERC20 token
160
+ * @param ownerAddress The address of the token owner
161
+ * @param provider An ethers.js provider
162
+ * @returns The current nonce
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * import { getPermitNonce } from "@ember-finance/sdk";
167
+ *
168
+ * const nonce = await getPermitNonce(
169
+ * tokenAddress,
170
+ * await signer.getAddress(),
171
+ * provider
172
+ * );
173
+ * ```
174
+ */
175
+ async function getPermitNonce(tokenAddress, ownerAddress, provider) {
176
+ const { Contract } = await Promise.resolve().then(() => __importStar(require("ethers")));
177
+ const tokenContract = new Contract(tokenAddress, ["function nonces(address owner) view returns (uint256)"], provider);
178
+ return await tokenContract.nonces(ownerAddress);
179
+ }
180
+ /**
181
+ * Helper function to create a permit signature with sensible defaults
182
+ *
183
+ * This is a convenience function that:
184
+ * - Fetches the current nonce automatically
185
+ * - Fetches the version from the token contract
186
+ * - Sets a deadline of 1 hour from now
187
+ * - Gets the chain ID from the signer
188
+ *
189
+ * @param signer The ethers.js signer (must be connected to a provider)
190
+ * @param tokenAddress The address of the ERC20 token (must support EIP-2612)
191
+ * @param tokenName The name of the token (for domain separator)
192
+ * @param spender The address authorized to spend (usually the vault address)
193
+ * @param value The amount of tokens to approve
194
+ * @returns The permit signature components
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * import { signPermitSimple } from "@ember-finance/sdk";
199
+ *
200
+ * // Simplified permit signing (fetches nonce, version, sets 1 hour deadline automatically)
201
+ * const permitSig = await signPermitSimple(
202
+ * signer,
203
+ * tokenAddress,
204
+ * "USD Coin",
205
+ * vaultAddress,
206
+ * amount
207
+ * );
208
+ *
209
+ * await userCalls.depositWithPermit(vaultAddress, amount, permitSig);
210
+ * ```
211
+ */
212
+ async function signPermitSimple(signer, tokenAddress, tokenName, spender, value) {
213
+ const provider = signer.provider;
214
+ if (!provider) {
215
+ throw new Error("Signer must be connected to a provider");
216
+ }
217
+ const ownerAddress = await signer.getAddress();
218
+ const network = await provider.getNetwork();
219
+ const chainId = network.chainId;
220
+ // Get current nonce and version from token contract
221
+ const nonce = await getPermitNonce(tokenAddress, ownerAddress, provider);
222
+ const version = await getPermitVersion(tokenAddress, provider);
223
+ // Set deadline to 1 hour from now
224
+ const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600);
225
+ return signPermit(signer, tokenAddress, tokenName, spender, value, deadline, nonce, chainId, version);
226
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ember-finance/sdk",
3
3
  "description": "Ember Protocol SDK",
4
- "version": "1.1.4",
4
+ "version": "1.2.0",
5
5
  "module": "./dist/index.js",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",