@ember-finance/sdk 1.1.4 → 1.2.1

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,134 @@
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 check if a token supports EIP-5267
62
+ *
63
+ * EIP-5267 defines a standard way to retrieve EIP-712 domain information
64
+ * via the eip712Domain() method. This is useful for tokens that want to
65
+ * expose their domain separator parameters in a standardized way.
66
+ *
67
+ * @param tokenAddress The address of the ERC20 token
68
+ * @param provider An ethers.js provider
69
+ * @returns True if the token supports EIP-5267, false otherwise
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * import { supportsEIP5267 } from "@ember-finance/sdk";
74
+ *
75
+ * const supports = await supportsEIP5267(tokenAddress, provider);
76
+ * if (supports) {
77
+ * console.log("Token supports EIP-5267");
78
+ * }
79
+ * ```
80
+ */
81
+ export declare function supportsEIP5267(tokenAddress: string, provider: import("ethers").Provider): Promise<boolean>;
82
+ /**
83
+ * Helper function to get the current nonce for a user from an EIP-2612 token
84
+ *
85
+ * @param tokenAddress The address of the ERC20 token
86
+ * @param ownerAddress The address of the token owner
87
+ * @param provider An ethers.js provider
88
+ * @returns The current nonce
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * import { getPermitNonce } from "@ember-finance/sdk";
93
+ *
94
+ * const nonce = await getPermitNonce(
95
+ * tokenAddress,
96
+ * await signer.getAddress(),
97
+ * provider
98
+ * );
99
+ * ```
100
+ */
101
+ export declare function getPermitNonce(tokenAddress: string, ownerAddress: string, provider: import("ethers").Provider): Promise<bigint>;
102
+ /**
103
+ * Helper function to create a permit signature with sensible defaults
104
+ *
105
+ * This is a convenience function that:
106
+ * - Fetches the current nonce automatically
107
+ * - Fetches the version from the token contract
108
+ * - Sets a deadline of 1 hour from now
109
+ * - Gets the chain ID from the signer
110
+ *
111
+ * @param signer The ethers.js signer (must be connected to a provider)
112
+ * @param tokenAddress The address of the ERC20 token (must support EIP-2612)
113
+ * @param tokenName The name of the token (for domain separator)
114
+ * @param spender The address authorized to spend (usually the vault address)
115
+ * @param value The amount of tokens to approve
116
+ * @returns The permit signature components
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * import { signPermitSimple } from "@ember-finance/sdk";
121
+ *
122
+ * // Simplified permit signing (fetches nonce, version, sets 1 hour deadline automatically)
123
+ * const permitSig = await signPermitSimple(
124
+ * signer,
125
+ * tokenAddress,
126
+ * "USD Coin",
127
+ * vaultAddress,
128
+ * amount
129
+ * );
130
+ *
131
+ * await userCalls.depositWithPermit(vaultAddress, amount, permitSig);
132
+ * ```
133
+ */
134
+ export declare function signPermitSimple(signer: Signer, tokenAddress: string, tokenName: string, spender: string, value: NumStr): Promise<IPermitSignature>;
@@ -0,0 +1,263 @@
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.supportsEIP5267 = supportsEIP5267;
39
+ exports.getPermitNonce = getPermitNonce;
40
+ exports.signPermitSimple = signPermitSimple;
41
+ /**
42
+ * Signs an EIP-2612 permit message
43
+ *
44
+ * This creates an off-chain signature that authorizes a spender (vault) to spend
45
+ * tokens on behalf of the owner without requiring a separate approval transaction.
46
+ *
47
+ * @param signer The ethers.js signer
48
+ * @param tokenAddress The address of the ERC20 token (must support EIP-2612)
49
+ * @param tokenName The name of the token (for domain separator)
50
+ * @param spender The address authorized to spend (usually the vault address)
51
+ * @param value The amount of tokens to approve
52
+ * @param deadline The deadline timestamp (in seconds) for the permit
53
+ * @param nonce The current permit nonce for the owner (fetch from token.nonces(owner))
54
+ * @param chainId The chain ID
55
+ * @param version Optional version string for the domain separator (fetched from token if not provided)
56
+ * @returns The permit signature components
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * import { signPermit } from "@ember-finance/sdk";
61
+ *
62
+ * const deadline = Math.floor(Date.now() / 1000) + 3600; // 1 hour from now
63
+ * const tokenContract = new ethers.Contract(tokenAddress, erc20Abi, provider);
64
+ * const nonce = await tokenContract.nonces(await signer.getAddress());
65
+ *
66
+ * const permitSig = await signPermit(
67
+ * signer,
68
+ * tokenAddress,
69
+ * "USD Coin", // token name
70
+ * vaultAddress,
71
+ * amount,
72
+ * BigInt(deadline),
73
+ * nonce,
74
+ * BigInt(1) // Ethereum mainnet
75
+ * );
76
+ *
77
+ * // Use with depositWithPermit
78
+ * await userCalls.depositWithPermit(vaultAddress, amount, permitSig);
79
+ * ```
80
+ */
81
+ async function signPermit(signer, tokenAddress, tokenName, spender, value, deadline, nonce, chainId, version) {
82
+ const owner = await signer.getAddress();
83
+ // If version not provided, fetch it from the token contract
84
+ let permitVersion = version;
85
+ if (!permitVersion) {
86
+ const provider = signer.provider;
87
+ if (!provider) {
88
+ throw new Error("Signer must be connected to a provider to fetch version");
89
+ }
90
+ permitVersion = await getPermitVersion(tokenAddress, provider);
91
+ }
92
+ // EIP-2612 domain
93
+ const domain = {
94
+ name: tokenName,
95
+ version: permitVersion,
96
+ chainId: chainId,
97
+ verifyingContract: tokenAddress
98
+ };
99
+ // EIP-2612 Permit type
100
+ const types = {
101
+ Permit: [
102
+ { name: "owner", type: "address" },
103
+ { name: "spender", type: "address" },
104
+ { name: "value", type: "uint256" },
105
+ { name: "nonce", type: "uint256" },
106
+ { name: "deadline", type: "uint256" }
107
+ ]
108
+ };
109
+ // Permit message
110
+ const message = {
111
+ owner,
112
+ spender,
113
+ value: BigInt(value),
114
+ nonce,
115
+ deadline
116
+ };
117
+ // Sign the typed data
118
+ const signature = await signer.signTypedData(domain, types, message);
119
+ // Split signature into v, r, s components
120
+ const r = signature.slice(0, 66);
121
+ const s = "0x" + signature.slice(66, 130);
122
+ const v = parseInt(signature.slice(130, 132), 16);
123
+ return {
124
+ deadline,
125
+ v,
126
+ r,
127
+ s
128
+ };
129
+ }
130
+ /**
131
+ * Helper function to get the permit version from an EIP-2612 token
132
+ *
133
+ * @param tokenAddress The address of the ERC20 token
134
+ * @param provider An ethers.js provider
135
+ * @returns The version string (e.g., "1", "2"), defaults to "1" if version() not implemented
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * import { getPermitVersion } from "@ember-finance/sdk";
140
+ *
141
+ * const version = await getPermitVersion(tokenAddress, provider);
142
+ * ```
143
+ */
144
+ async function getPermitVersion(tokenAddress, provider) {
145
+ try {
146
+ const { Contract } = await Promise.resolve().then(() => __importStar(require("ethers")));
147
+ const tokenContract = new Contract(tokenAddress, ["function version() view returns (string)"], provider);
148
+ return await tokenContract.version();
149
+ }
150
+ catch (error) {
151
+ // TODO: change this to "1" when we have a token that supports version "1"
152
+ // If version() is not implemented, default to "2"
153
+ // Most EIP-2612 tokens use version "2" unless specified otherwise
154
+ return "2";
155
+ }
156
+ }
157
+ /**
158
+ * Helper function to check if a token supports EIP-5267
159
+ *
160
+ * EIP-5267 defines a standard way to retrieve EIP-712 domain information
161
+ * via the eip712Domain() method. This is useful for tokens that want to
162
+ * expose their domain separator parameters in a standardized way.
163
+ *
164
+ * @param tokenAddress The address of the ERC20 token
165
+ * @param provider An ethers.js provider
166
+ * @returns True if the token supports EIP-5267, false otherwise
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * import { supportsEIP5267 } from "@ember-finance/sdk";
171
+ *
172
+ * const supports = await supportsEIP5267(tokenAddress, provider);
173
+ * if (supports) {
174
+ * console.log("Token supports EIP-5267");
175
+ * }
176
+ * ```
177
+ */
178
+ async function supportsEIP5267(tokenAddress, provider) {
179
+ try {
180
+ const { Contract } = await Promise.resolve().then(() => __importStar(require("ethers")));
181
+ const tokenContract = new Contract(tokenAddress, [
182
+ "function eip712Domain() view returns (bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions)"
183
+ ], provider);
184
+ // Try to call the method - if it succeeds, the token supports EIP-5267
185
+ await tokenContract.eip712Domain();
186
+ return true;
187
+ }
188
+ catch (error) {
189
+ // If the call fails, the token does not support EIP-5267
190
+ return false;
191
+ }
192
+ }
193
+ /**
194
+ * Helper function to get the current nonce for a user from an EIP-2612 token
195
+ *
196
+ * @param tokenAddress The address of the ERC20 token
197
+ * @param ownerAddress The address of the token owner
198
+ * @param provider An ethers.js provider
199
+ * @returns The current nonce
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * import { getPermitNonce } from "@ember-finance/sdk";
204
+ *
205
+ * const nonce = await getPermitNonce(
206
+ * tokenAddress,
207
+ * await signer.getAddress(),
208
+ * provider
209
+ * );
210
+ * ```
211
+ */
212
+ async function getPermitNonce(tokenAddress, ownerAddress, provider) {
213
+ const { Contract } = await Promise.resolve().then(() => __importStar(require("ethers")));
214
+ const tokenContract = new Contract(tokenAddress, ["function nonces(address owner) view returns (uint256)"], provider);
215
+ return await tokenContract.nonces(ownerAddress);
216
+ }
217
+ /**
218
+ * Helper function to create a permit signature with sensible defaults
219
+ *
220
+ * This is a convenience function that:
221
+ * - Fetches the current nonce automatically
222
+ * - Fetches the version from the token contract
223
+ * - Sets a deadline of 1 hour from now
224
+ * - Gets the chain ID from the signer
225
+ *
226
+ * @param signer The ethers.js signer (must be connected to a provider)
227
+ * @param tokenAddress The address of the ERC20 token (must support EIP-2612)
228
+ * @param tokenName The name of the token (for domain separator)
229
+ * @param spender The address authorized to spend (usually the vault address)
230
+ * @param value The amount of tokens to approve
231
+ * @returns The permit signature components
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * import { signPermitSimple } from "@ember-finance/sdk";
236
+ *
237
+ * // Simplified permit signing (fetches nonce, version, sets 1 hour deadline automatically)
238
+ * const permitSig = await signPermitSimple(
239
+ * signer,
240
+ * tokenAddress,
241
+ * "USD Coin",
242
+ * vaultAddress,
243
+ * amount
244
+ * );
245
+ *
246
+ * await userCalls.depositWithPermit(vaultAddress, amount, permitSig);
247
+ * ```
248
+ */
249
+ async function signPermitSimple(signer, tokenAddress, tokenName, spender, value) {
250
+ const provider = signer.provider;
251
+ if (!provider) {
252
+ throw new Error("Signer must be connected to a provider");
253
+ }
254
+ const ownerAddress = await signer.getAddress();
255
+ const network = await provider.getNetwork();
256
+ const chainId = network.chainId;
257
+ // Get current nonce and version from token contract
258
+ const nonce = await getPermitNonce(tokenAddress, ownerAddress, provider);
259
+ const version = await getPermitVersion(tokenAddress, provider);
260
+ // Set deadline to 1 hour from now
261
+ const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600);
262
+ return signPermit(signer, tokenAddress, tokenName, spender, value, deadline, nonce, chainId, version);
263
+ }
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.1",
5
5
  "module": "./dist/index.js",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",