@cowprotocol/permit-utils 0.0.2 → 0.1.1-RC.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.
package/const.d.ts CHANGED
@@ -1,7 +1,6 @@
1
- import { SupportedChainId } from '@cowprotocol/cow-sdk';
2
1
  import { Wallet } from '@ethersproject/wallet';
3
2
  export declare const PERMIT_SIGNER: Wallet;
4
- export declare const PERMIT_GAS_LIMIT_MIN: Record<SupportedChainId, number>;
3
+ export declare const PERMIT_GAS_LIMIT_MIN: Record<number, number>;
5
4
  export declare const DEFAULT_PERMIT_GAS_LIMIT = "80000";
6
5
  export declare const DEFAULT_PERMIT_VALUE: string;
7
6
  export declare const DEFAULT_PERMIT_DURATION: number;
package/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("@cowprotocol/cow-sdk"),U=require("@ethersproject/constants"),H=require("@ethersproject/wallet"),p=require("@1inch/permit-signed-approvals-utils"),C=require("@ethersproject/abi"),O=require("@ethersproject/bignumber"),F=require("@ethersproject/contracts"),G=require("@ethersproject/address"),q="0x4dae303b820e9878cafeb0f84edcc015e8a81b1bff510e824e4fc27544e458dd",h=new H.Wallet(q),x={[f.SupportedChainId.MAINNET]:55e3,[f.SupportedChainId.GNOSIS_CHAIN]:55e3,[f.SupportedChainId.SEPOLIA]:55e3,[f.SupportedChainId.GOERLI]:36e3},T="80000",A=U.MaxUint256.toString(),K=157788e6,V=new Set(["0x6b175474e89094c44da98b954eedeac495271d0f"]);function D(t){return t==="USD//C"?"USD Coin":t}async function B(t,n,e,o,a,r,{version:i,type:c,name:d}){const l=d||a;if(c==="unsupported")return!1;if(!l)throw new Error(`No token name for ${o}`);const m={chainId:n,tokenName:D(l),tokenAddress:o,callData:r,version:i};let u;if(r.startsWith(p.EIP_2612_PERMIT_SELECTOR)?u=e.recoverPermitOwnerFromCallData({...m,callData:r.replace(p.EIP_2612_PERMIT_SELECTOR,"0x")}):r.startsWith(p.DAI_PERMIT_SELECTOR)&&(u=e.recoverDaiLikePermitOwnerFromCallData({...m,callData:r.replace(p.DAI_PERMIT_SELECTOR,"0x")})),!!u)try{return(await u).toLowerCase()===t.toLowerCase()}catch(s){return console.debug(`[checkHasValidPendingPermit] Failed to check permit validity for owner ${t} with callData ${r}`,s),!1}}async function R({eip2162Utils:t,callDataParams:n}){const[e,o,a,...r]=n;return(await t.buildPermitCallData(e,o,D(a),...r)).replace("0x",p.EIP_2612_PERMIT_SELECTOR)}async function v({eip2162Utils:t,callDataParams:n}){return(await t.buildDaiLikePermitCallData(...n)).replace("0x",p.DAI_PERMIT_SELECTOR)}function E(){return Math.ceil((Date.now()+K)/1e3)}function L(t){return!!t&&t.type!=="unsupported"}const I={};async function j(t){const n=Y(t),e=I[n];if(e)try{return await e}catch(a){console.debug("[generatePermitHookWith] cached request failed",a),delete I[n]}const o=W(t).then(a=>(delete I[n],a));return I[n]=o,o}async function W(t){const{inputToken:n,spender:e,chainId:o,permitInfo:a,provider:r,account:i,eip2162Utils:c,nonce:d}=t,l=n.address,m=a.name||n.name;if(!L(a))throw new Error(`Trying to generate permit hook for unsupported token: ${l}`);if(!m)throw new Error(`No token name for token: ${l}`);const u=i||h.address,s=d===void 0?await c.getTokenNonce(l,u):d,P=E(),k=A,w=a.type==="eip-2612"?await R({eip2162Utils:c,callDataParams:[{owner:u,spender:e,value:k,nonce:s,deadline:P},o,m,l,a.version]}):await v({eip2162Utils:c,callDataParams:[{holder:u,spender:e,allowed:!0,value:k,nonce:s,expiry:P},o,m,l,a.version]}),M=await Q(w,u,l,r,!!i);return{target:l,callData:w,gasLimit:M}}async function Q(t,n,e,o,a){try{const r=await o.estimateGas({data:t,from:n,to:e}),i=a?r:r.add(r.div(10));return i.gt(T)?i.toString():T}catch(r){return console.debug("[calculatePermitGasLimit] Failed to estimateGas, using default",r),T}}function Y(t){const{inputToken:n,chainId:e,account:o}=t;return`${n.address.toLowerCase()}-${e}${o?`-${o.toLowerCase()}`:""}`}function N(t,n,e){return new F.Contract(t,n,e)}class z{constructor(n,e){this.provider=n,this.walletSigner=e}contractEncodeABI(n,e,o,a){return N(e||"",n,this.provider).interface.encodeFunctionData(o,a)}signTypedData(n,e,o){const a=Object.keys(e.types).reduce((i,c)=>(c!=="EIP712Domain"&&(i[c]=e.types[c]),i),{});return(this.walletSigner||this.provider.getSigner())._signTypedData(e.domain,a,e.message)}ethCall(n,e){return this.provider.call({to:n,data:e})}decodeABIParameter(n,e){return C.defaultAbiCoder.decode([n],e)[0]}decodeABIParameters(n,e){const o=C.defaultAbiCoder.decode(n,e);if(o&&typeof o=="object"){const a={};return Object.keys(o).forEach(r=>{const i=o[r];O.BigNumber.isBigNumber(i)?a[r]=i.toHexString():a[r]=i}),a}return o}}const _=new Map,S=new Map;function $(t,n,e){const o=_.get(t);if(!e&&o)return o;const a=`${t}-${e}`,r=S.get(a);if(r)return r;const i=new z(n,e?void 0:h),c=new p.Eip2612PermitUtils(i);return e?(console.log(`[getPermitUtilsInstance] Set cached provider utils for chain ${t}-${e}`,c),S.set(a,c)):(console.log(`[getPermitUtilsInstance] Set cached chain utils for chain ${t}`,c),_.set(t,c)),c}const J=[{constant:!0,inputs:[],name:"name",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"}];async function X(t,n,e){const o=G.getAddress(t);return N(o,J,e).callStatic.name()}const Z={value:A,nonce:0,deadline:E()},ee={allowed:!0,nonce:0,expiry:E()},y={},g={type:"unsupported"};async function te(t){const{tokenAddress:n,chainId:e}=t,o=`${e}-${n.toLowerCase()}`,a=y[o];if(a)return a;const r=ne(t);return y[o]=r,r}async function ne(t){const{spender:n,tokenAddress:e,tokenName:o,chainId:a,provider:r}=t,i=$(a,r),c=h.address;let d=o;try{d=await X(e,a,r)}catch(s){if(/ETIMEDOUT/.test(s)&&!d)return{error:"Failed to fetch token name from contract. RPC connection error"};console.debug(`[checkTokenIsPermittable] Couldn't fetch token name from the contract for token ${e}, using provided '${d}'`,s)}if(!d)return{error:`Token name could not be determined for ${e}`};let l;try{l=await i.getTokenNonce(e,c)}catch(s){return s==="nonce not supported"||s.message==="nonce is NaN"?(console.debug(`[checkTokenIsPermittable] Not a permittable token ${e} - ${d}`,s?.message||s),{...g,name:d}):(console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${e} - ${d}`,s),{error:s.message||s.toString()})}let m;if(!V.has(e))try{m=await i.getTokenVersion(e)}catch(s){console.debug(`[checkTokenIsPermittable] Failed to get version for ${e} - ${d}`,s)}const u={chainId:a,eip2612PermitUtils:i,nonce:l,spender:n,tokenAddress:e,tokenName:d,walletAddress:c,version:m};try{return await b({...u,type:"eip-2612",provider:r})}catch(s){try{return await oe(e,i)?await b({...u,type:"dai-like",provider:r}):/invalid signature/.test(s)||s?.code==="UNPREDICTABLE_GAS_LIMIT"?(console.debug(`[checkTokenIsPermittable] Token ${e} - ${d} might be permittable, but it's not supported for now. Reason:`,s?.reason),{...g,name:d}):(console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${e} - ${d}`,s),{error:s.message||s.toString()})}catch(P){return console.debug(`[checkTokenIsPermittable] Failed to estimate dai-like permit for ${e} - ${d}`,P),{error:P.message||P.toString()}}}}async function b(t){const{provider:n,chainId:e,walletAddress:o,tokenAddress:a,tokenName:r,type:i,version:c}=t,l=await(i==="eip-2612"?re:ae)(t);return l?(await n.estimateGas({data:l,from:o,to:a})).toNumber()>x[e]?{type:i,version:c,name:r}:{...g,name:r}:{...g,name:r}}async function re(t){const{eip2612PermitUtils:n,walletAddress:e,spender:o,nonce:a,chainId:r,tokenName:i,tokenAddress:c,version:d}=t;return R({eip2162Utils:n,callDataParams:[{...Z,owner:e,spender:o,nonce:a},+r,i,c,d]})}async function oe(t,n){return await n.getPermitTypeHash(t)===p.DAI_LIKE_PERMIT_TYPEHASH}async function ae(t){const{eip2612PermitUtils:n,tokenAddress:e,walletAddress:o,spender:a,nonce:r,chainId:i,tokenName:c,version:d}=t;return await n.getPermitTypeHash(e)===p.DAI_LIKE_PERMIT_TYPEHASH?v({eip2162Utils:n,callDataParams:[{...ee,holder:o,spender:a,nonce:r},i,c,e,d]}):!1}exports.PERMIT_SIGNER=h;exports.checkIsCallDataAValidPermit=B;exports.generatePermitHook=j;exports.getPermitUtilsInstance=$;exports.getTokenPermitInfo=te;exports.isSupportedPermitInfo=L;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const H=require("@ethersproject/constants"),O=require("@ethersproject/wallet"),p=require("@1inch/permit-signed-approvals-utils"),C=require("@ethersproject/abi"),F=require("@ethersproject/bignumber"),x=require("@ethersproject/contracts"),v=require("@ethersproject/address"),G="0x4dae303b820e9878cafeb0f84edcc015e8a81b1bff510e824e4fc27544e458dd",I=new O.Wallet(G),h=55e3,q={1:h,100:h,11155111:h,5:36e3},T="80000",S=H.MaxUint256.toString(),K=157788e6,V=new Set(["0x6b175474e89094c44da98b954eedeac495271d0f"]);async function B(r,t,e,a,n,o,{version:c,type:s,name:l}){const d=l||n;if(s==="unsupported")return!1;if(!d)throw new Error(`No token name for ${a}`);const m={chainId:t,tokenName:d,tokenAddress:a,callData:o,version:c};let u;if(o.startsWith(p.EIP_2612_PERMIT_SELECTOR)?u=e.recoverPermitOwnerFromCallData({...m,callData:o.replace(p.EIP_2612_PERMIT_SELECTOR,"0x")}):o.startsWith(p.DAI_PERMIT_SELECTOR)&&(u=e.recoverDaiLikePermitOwnerFromCallData({...m,callData:o.replace(p.DAI_PERMIT_SELECTOR,"0x")})),!!u)try{return(await u).toLowerCase()===r.toLowerCase()}catch(i){return console.debug(`[checkHasValidPendingPermit] Failed to check permit validity for owner ${r} with callData ${o}`,i),!1}}async function L({eip2162Utils:r,callDataParams:t}){const[e,a,n,...o]=t;return(await r.buildPermitCallData(e,a,n,...o)).replace("0x",p.EIP_2612_PERMIT_SELECTOR)}async function R({eip2162Utils:r,callDataParams:t}){return(await r.buildDaiLikePermitCallData(...t)).replace("0x",p.DAI_PERMIT_SELECTOR)}function y(){return Math.ceil((Date.now()+K)/1e3)}function $(r){return!!r&&r.type!=="unsupported"}const g={};async function j(r){const t=Y(r),e=g[t];if(e)try{return await e}catch(n){console.debug("[generatePermitHookWith] cached request failed",n),delete g[t]}const a=W(r).then(n=>(delete g[t],n));return g[t]=a,a}async function W(r){const{inputToken:t,spender:e,chainId:a,permitInfo:n,provider:o,account:c,eip2162Utils:s,nonce:l}=r,d=t.address,m=n.name||t.name;if(!$(n))throw new Error(`Trying to generate permit hook for unsupported token: ${d}`);if(!m)throw new Error(`No token name for token: ${d}`);const u=c||I.address,i=l===void 0?await s.getTokenNonce(d,u):l,f=y(),w=S,k=n.type==="eip-2612"?await L({eip2162Utils:s,callDataParams:[{owner:u,spender:e,value:w,nonce:i,deadline:f},a,m,d,n.version]}):await R({eip2162Utils:s,callDataParams:[{holder:u,spender:e,allowed:!0,value:w,nonce:i,expiry:f},a,m,d,n.version]}),U=await Q(k,u,d,o,!!c);return{target:d,callData:k,gasLimit:U}}async function Q(r,t,e,a,n){try{const o=await a.estimateGas({data:r,from:t,to:e}),c=n?o:o.add(o.div(10));return c.gt(T)?c.toString():T}catch(o){return console.debug("[calculatePermitGasLimit] Failed to estimateGas, using default",o),T}}function Y(r){const{inputToken:t,chainId:e,account:a}=r;return`${t.address.toLowerCase()}-${e}${a?`-${a.toLowerCase()}`:""}`}function E(r,t,e){return new x.Contract(r,t,e)}class z{constructor(t,e){this.provider=t,this.walletSigner=e}contractEncodeABI(t,e,a,n){return E(e||"",t,this.provider).interface.encodeFunctionData(a,n)}signTypedData(t,e,a){const n=Object.keys(e.types).reduce((c,s)=>(s!=="EIP712Domain"&&(c[s]=e.types[s]),c),{});return(this.walletSigner||this.provider.getSigner())._signTypedData(e.domain,n,e.message)}ethCall(t,e){return this.provider.call({to:t,data:e})}decodeABIParameter(t,e){return C.defaultAbiCoder.decode([t],e)[0]}decodeABIParameters(t,e){const a=C.defaultAbiCoder.decode(t,e);if(a&&typeof a=="object"){const n={};return Object.keys(a).forEach(o=>{const c=a[o];F.BigNumber.isBigNumber(c)?n[o]=c.toHexString():n[o]=c}),n}return a}}const b=new Map,_=new Map;function M(r,t,e){const a=b.get(r);if(!e&&a)return a;const n=`${r}-${e}`,o=_.get(n);if(o)return o;const c=new z(t,e?void 0:I),s=new p.Eip2612PermitUtils(c);return e?(console.log(`[getPermitUtilsInstance] Set cached provider utils for chain ${r}-${e}`,s),_.set(n,s)):(console.log(`[getPermitUtilsInstance] Set cached chain utils for chain ${r}`,s),b.set(r,s)),s}const N=[{constant:!0,inputs:[],name:"name",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{inputs:[],name:"eip712Domain",outputs:[{internalType:"bytes1",name:"fields",type:"bytes1"},{internalType:"string",name:"name",type:"string"},{internalType:"string",name:"version",type:"string"},{internalType:"uint256",name:"chainId",type:"uint256"},{internalType:"address",name:"verifyingContract",type:"address"},{internalType:"bytes32",name:"salt",type:"bytes32"},{internalType:"uint256[]",name:"extensions",type:"uint256[]"}],stateMutability:"view",type:"function"}];async function J(r,t,e){const a=v.getAddress(r),o=await E(a,N,e).callStatic.eip712Domain();return X(o,t,r)}async function X(r,t,e){const{extensions:a,...n}=r;if(a.length>0)throw Error("Extensions not implemented");if(n.chainId&&t!==parseInt(n.chainId,16))throw Error(`ChainId mismatch. Received: '${n.chainId}', expected: '${t}'`);if(n.verifyingContract&&e.toLowerCase()!==n.verifyingContract.toLowerCase())throw Error(`Address mismatch. Received: '${n.verifyingContract}', expected: '${e}'`);return ee(n)}const Z=["name","version","chainId","verifyingContract","salt"];function ee(r){const t=parseInt(r.fields,16);return Z.reduce((e,a,n)=>(t&1<<n&&(e[a]=r[a]),e),{})}async function te(r,t,e){const a=v.getAddress(r);return E(a,N,e).callStatic.name()}const ne={value:S,nonce:0,deadline:y()},re={allowed:!0,nonce:0,expiry:y()},A={},P={type:"unsupported"};async function ae(r){const{tokenAddress:t,chainId:e}=r,a=`${e}-${t.toLowerCase()}`,n=A[a];if(n)return n;const o=oe(r);return A[a]=o,o}async function oe(r){const{spender:t,tokenAddress:e,chainId:a,provider:n}=r,o=M(a,n),c=I.address;let s;try{s=await J(e,a,n)}catch(i){console.debug(`[checkTokenIsPermittable] Couldn't fetch eip712domain for token ${e}`,i)}let l=s==null?void 0:s.name;try{l||(l=await te(e,a,n))}catch(i){if(/ETIMEDOUT/.test(i)&&!l)return{error:"Failed to fetch token name from contract. RPC connection error"};console.debug(`[checkTokenIsPermittable] Couldn't fetch token name from the contract for token ${e}, using provided '${l}'`,i)}if(!l)return{error:`Token name could not be determined for ${e}`};let d;try{d=await o.getTokenNonce(e,c)}catch(i){return i==="nonce not supported"||i.message==="nonce is NaN"?(console.debug(`[checkTokenIsPermittable] Not a permittable token ${e} - ${l}`,(i==null?void 0:i.message)||i),{...P,name:l}):(console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${e} - ${l}`,i),{error:i.message||i.toString()})}let m=s==null?void 0:s.version;if(!V.has(e)&&m===void 0)try{m=await o.getTokenVersion(e)}catch(i){console.debug(`[checkTokenIsPermittable] Failed to get version for ${e} - ${l}`,i)}const u={chainId:a,eip2612PermitUtils:o,nonce:d,spender:t,tokenAddress:e,tokenName:l,walletAddress:c,version:m};try{return await D({...u,type:"eip-2612",provider:n})}catch(i){try{return await se(e,o)?await D({...u,type:"dai-like",provider:n}):/invalid signature/.test(i)||(i==null?void 0:i.code)==="UNPREDICTABLE_GAS_LIMIT"?(console.debug(`[checkTokenIsPermittable] Token ${e} - ${l} might be permittable, but it's not supported for now. Reason:`,i==null?void 0:i.reason),{...P,name:l}):(console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${e} - ${l}`,i),{error:i.message||i.toString()})}catch(f){return console.debug(`[checkTokenIsPermittable] Failed to estimate dai-like permit for ${e} - ${l}`,f),{error:f.message||f.toString()}}}}async function D(r){const{provider:t,chainId:e,walletAddress:a,tokenAddress:n,tokenName:o,type:c,version:s}=r,d=await(c==="eip-2612"?ie:ce)(r);return d?(await t.estimateGas({data:d,from:a,to:n})).toNumber()>q[e]?{type:c,version:s,name:o}:{...P,name:o}:{...P,name:o}}async function ie(r){const{eip2612PermitUtils:t,walletAddress:e,spender:a,nonce:n,chainId:o,tokenName:c,tokenAddress:s,version:l}=r;return L({eip2162Utils:t,callDataParams:[{...ne,owner:e,spender:a,nonce:n},+o,c,s,l]})}async function se(r,t){return await t.getPermitTypeHash(r)===p.DAI_LIKE_PERMIT_TYPEHASH}async function ce(r){const{eip2612PermitUtils:t,tokenAddress:e,walletAddress:a,spender:n,nonce:o,chainId:c,tokenName:s,version:l}=r;return await t.getPermitTypeHash(e)===p.DAI_LIKE_PERMIT_TYPEHASH?R({eip2162Utils:t,callDataParams:[{...re,holder:a,spender:n,nonce:o},c,s,e,l]}):!1}exports.PERMIT_SIGNER=I;exports.checkIsCallDataAValidPermit=B;exports.generatePermitHook=j;exports.getPermitUtilsInstance=M;exports.getTokenPermitInfo=ae;exports.isSupportedPermitInfo=$;
package/index.js CHANGED
@@ -1,194 +1,190 @@
1
- import { SupportedChainId as f } from "@cowprotocol/cow-sdk";
2
- import { MaxUint256 as M } from "@ethersproject/constants";
3
- import { Wallet as H } from "@ethersproject/wallet";
4
- import { EIP_2612_PERMIT_SELECTOR as k, DAI_PERMIT_SELECTOR as I, Eip2612PermitUtils as O, DAI_LIKE_PERMIT_TYPEHASH as S } from "@1inch/permit-signed-approvals-utils";
5
- import { defaultAbiCoder as C } from "@ethersproject/abi";
6
- import { BigNumber as F } from "@ethersproject/bignumber";
1
+ import { MaxUint256 as H } from "@ethersproject/constants";
2
+ import { Wallet as F } from "@ethersproject/wallet";
3
+ import { EIP_2612_PERMIT_SELECTOR as P, DAI_PERMIT_SELECTOR as I, Eip2612PermitUtils as x, DAI_LIKE_PERMIT_TYPEHASH as L } from "@1inch/permit-signed-approvals-utils";
4
+ import { defaultAbiCoder as b } from "@ethersproject/abi";
5
+ import { BigNumber as O } from "@ethersproject/bignumber";
7
6
  import { Contract as G } from "@ethersproject/contracts";
8
- import { getAddress as x } from "@ethersproject/address";
9
- const K = "0x4dae303b820e9878cafeb0f84edcc015e8a81b1bff510e824e4fc27544e458dd", T = new H(K), V = {
10
- [f.MAINNET]: 55e3,
11
- [f.GNOSIS_CHAIN]: 55e3,
12
- [f.SEPOLIA]: 55e3,
13
- [f.GOERLI]: 36e3
14
- }, h = "80000", v = M.toString(), B = 157788e6, q = /* @__PURE__ */ new Set(["0x6b175474e89094c44da98b954eedeac495271d0f"]);
15
- function L(t) {
16
- return t === "USD//C" ? "USD Coin" : t;
17
- }
18
- async function fe(t, n, e, o, a, r, {
19
- version: i,
20
- type: c,
7
+ import { getAddress as $ } from "@ethersproject/address";
8
+ const K = "0x4dae303b820e9878cafeb0f84edcc015e8a81b1bff510e824e4fc27544e458dd", T = new F(K), h = 55e3, B = {
9
+ 1: h,
10
+ 100: h,
11
+ 11155111: h,
12
+ 5: 36e3
13
+ }, y = "80000", S = H.toString(), V = 157788e6, q = /* @__PURE__ */ new Set(["0x6b175474e89094c44da98b954eedeac495271d0f"]);
14
+ async function he(r, t, e, a, n, o, {
15
+ version: c,
16
+ type: s,
21
17
  name: l
22
18
  }) {
23
- const d = l || a;
24
- if (c === "unsupported")
19
+ const d = l || n;
20
+ if (s === "unsupported")
25
21
  return !1;
26
22
  if (!d)
27
- throw new Error(`No token name for ${o}`);
23
+ throw new Error(`No token name for ${a}`);
28
24
  const u = {
29
- chainId: n,
30
- tokenName: L(d),
31
- tokenAddress: o,
32
- callData: r,
33
- version: i
25
+ chainId: t,
26
+ tokenName: d,
27
+ tokenAddress: a,
28
+ callData: o,
29
+ version: c
34
30
  };
35
31
  let m;
36
- if (r.startsWith(k) ? m = e.recoverPermitOwnerFromCallData({
32
+ if (o.startsWith(P) ? m = e.recoverPermitOwnerFromCallData({
37
33
  ...u,
38
34
  // I don't know why this was removed, ok?
39
35
  // We added it back on buildPermitCallData.ts
40
36
  // But it looks like this is needed 🤷
41
37
  // Check the test for this method https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.test.ts#L85-L106
42
- callData: r.replace(k, "0x")
43
- }) : r.startsWith(I) && (m = e.recoverDaiLikePermitOwnerFromCallData({
38
+ callData: o.replace(P, "0x")
39
+ }) : o.startsWith(I) && (m = e.recoverDaiLikePermitOwnerFromCallData({
44
40
  ...u,
45
- callData: r.replace(I, "0x")
41
+ callData: o.replace(I, "0x")
46
42
  })), !!m)
47
43
  try {
48
- return (await m).toLowerCase() === t.toLowerCase();
49
- } catch (s) {
50
- return console.debug(`[checkHasValidPendingPermit] Failed to check permit validity for owner ${t} with callData ${r}`, s), !1;
44
+ return (await m).toLowerCase() === r.toLowerCase();
45
+ } catch (i) {
46
+ return console.debug(`[checkHasValidPendingPermit] Failed to check permit validity for owner ${r} with callData ${o}`, i), !1;
51
47
  }
52
48
  }
53
- async function N({
54
- eip2162Utils: t,
55
- callDataParams: n
49
+ async function R({
50
+ eip2162Utils: r,
51
+ callDataParams: t
56
52
  }) {
57
- const [e, o, a, ...r] = n;
58
- return (await t.buildPermitCallData(e, o, L(a), ...r)).replace("0x", k);
53
+ const [e, a, n, ...o] = t;
54
+ return (await r.buildPermitCallData(e, a, n, ...o)).replace("0x", P);
59
55
  }
60
- async function $({
61
- eip2162Utils: t,
62
- callDataParams: n
56
+ async function N({
57
+ eip2162Utils: r,
58
+ callDataParams: t
63
59
  }) {
64
- return (await t.buildDaiLikePermitCallData(...n)).replace("0x", I);
60
+ return (await r.buildDaiLikePermitCallData(...t)).replace("0x", I);
65
61
  }
66
62
  function w() {
67
- return Math.ceil((Date.now() + B) / 1e3);
63
+ return Math.ceil((Date.now() + V) / 1e3);
68
64
  }
69
- function W(t) {
70
- return !!t && t.type !== "unsupported";
65
+ function W(r) {
66
+ return !!r && r.type !== "unsupported";
71
67
  }
72
- const g = {};
73
- async function ge(t) {
74
- const n = Y(t), e = g[n];
68
+ const f = {};
69
+ async function ye(r) {
70
+ const t = Y(r), e = f[t];
75
71
  if (e)
76
72
  try {
77
73
  return await e;
78
- } catch (a) {
79
- console.debug("[generatePermitHookWith] cached request failed", a), delete g[n];
74
+ } catch (n) {
75
+ console.debug("[generatePermitHookWith] cached request failed", n), delete f[t];
80
76
  }
81
- const o = j(t).then((a) => (delete g[n], a));
82
- return g[n] = o, o;
77
+ const a = j(r).then((n) => (delete f[t], n));
78
+ return f[t] = a, a;
83
79
  }
84
- async function j(t) {
80
+ async function j(r) {
85
81
  const {
86
- inputToken: n,
82
+ inputToken: t,
87
83
  spender: e,
88
- chainId: o,
89
- permitInfo: a,
90
- provider: r,
91
- account: i,
92
- eip2162Utils: c,
84
+ chainId: a,
85
+ permitInfo: n,
86
+ provider: o,
87
+ account: c,
88
+ eip2162Utils: s,
93
89
  nonce: l
94
- } = t, d = n.address, u = a.name || n.name;
95
- if (!W(a))
90
+ } = r, d = t.address, u = n.name || t.name;
91
+ if (!W(n))
96
92
  throw new Error(`Trying to generate permit hook for unsupported token: ${d}`);
97
93
  if (!u)
98
94
  throw new Error(`No token name for token: ${d}`);
99
- const m = i || T.address, s = l === void 0 ? await c.getTokenNonce(d, m) : l, p = w(), E = v, y = a.type === "eip-2612" ? await N({
100
- eip2162Utils: c,
95
+ const m = c || T.address, i = l === void 0 ? await s.getTokenNonce(d, m) : l, p = w(), E = S, C = n.type === "eip-2612" ? await R({
96
+ eip2162Utils: s,
101
97
  callDataParams: [{
102
98
  owner: m,
103
99
  spender: e,
104
100
  value: E,
105
- nonce: s,
101
+ nonce: i,
106
102
  deadline: p
107
- }, o, u, d, a.version]
108
- }) : await $({
109
- eip2162Utils: c,
103
+ }, a, u, d, n.version]
104
+ }) : await N({
105
+ eip2162Utils: s,
110
106
  callDataParams: [{
111
107
  holder: m,
112
108
  spender: e,
113
109
  allowed: !0,
114
110
  value: E,
115
- nonce: s,
111
+ nonce: i,
116
112
  expiry: p
117
- }, o, u, d, a.version]
118
- }), U = await Q(y, m, d, r, !!i);
113
+ }, a, u, d, n.version]
114
+ }), U = await Q(C, m, d, o, !!c);
119
115
  return {
120
116
  target: d,
121
- callData: y,
117
+ callData: C,
122
118
  gasLimit: U
123
119
  };
124
120
  }
125
- async function Q(t, n, e, o, a) {
121
+ async function Q(r, t, e, a, n) {
126
122
  try {
127
- const r = await o.estimateGas({
128
- data: t,
129
- from: n,
123
+ const o = await a.estimateGas({
124
+ data: r,
125
+ from: t,
130
126
  to: e
131
- }), i = a ? r : r.add(r.div(10));
132
- return i.gt(h) ? i.toString() : h;
133
- } catch (r) {
134
- return console.debug("[calculatePermitGasLimit] Failed to estimateGas, using default", r), h;
127
+ }), c = n ? o : o.add(o.div(10));
128
+ return c.gt(y) ? c.toString() : y;
129
+ } catch (o) {
130
+ return console.debug("[calculatePermitGasLimit] Failed to estimateGas, using default", o), y;
135
131
  }
136
132
  }
137
- function Y(t) {
133
+ function Y(r) {
138
134
  const {
139
- inputToken: n,
135
+ inputToken: t,
140
136
  chainId: e,
141
- account: o
142
- } = t;
143
- return `${n.address.toLowerCase()}-${e}${o ? `-${o.toLowerCase()}` : ""}`;
137
+ account: a
138
+ } = r;
139
+ return `${t.address.toLowerCase()}-${e}${a ? `-${a.toLowerCase()}` : ""}`;
144
140
  }
145
- function R(t, n, e) {
146
- return new G(t, n, e);
141
+ function k(r, t, e) {
142
+ return new G(r, t, e);
147
143
  }
148
144
  class z {
149
- constructor(n, e) {
150
- this.provider = n, this.walletSigner = e;
145
+ constructor(t, e) {
146
+ this.provider = t, this.walletSigner = e;
151
147
  }
152
- contractEncodeABI(n, e, o, a) {
153
- return R(e || "", n, this.provider).interface.encodeFunctionData(o, a);
148
+ contractEncodeABI(t, e, a, n) {
149
+ return k(e || "", t, this.provider).interface.encodeFunctionData(a, n);
154
150
  }
155
- signTypedData(n, e, o) {
156
- const a = Object.keys(e.types).reduce((i, c) => (c !== "EIP712Domain" && (i[c] = e.types[c]), i), {});
157
- return (this.walletSigner || this.provider.getSigner())._signTypedData(e.domain, a, e.message);
151
+ signTypedData(t, e, a) {
152
+ const n = Object.keys(e.types).reduce((c, s) => (s !== "EIP712Domain" && (c[s] = e.types[s]), c), {});
153
+ return (this.walletSigner || this.provider.getSigner())._signTypedData(e.domain, n, e.message);
158
154
  }
159
- ethCall(n, e) {
155
+ ethCall(t, e) {
160
156
  return this.provider.call({
161
- to: n,
157
+ to: t,
162
158
  data: e
163
159
  });
164
160
  }
165
- decodeABIParameter(n, e) {
166
- return C.decode([n], e)[0];
161
+ decodeABIParameter(t, e) {
162
+ return b.decode([t], e)[0];
167
163
  }
168
- decodeABIParameters(n, e) {
169
- const o = C.decode(n, e);
170
- if (o && typeof o == "object") {
171
- const a = {};
172
- return Object.keys(o).forEach((r) => {
173
- const i = o[r];
174
- F.isBigNumber(i) ? a[r] = i.toHexString() : a[r] = i;
175
- }), a;
164
+ decodeABIParameters(t, e) {
165
+ const a = b.decode(t, e);
166
+ if (a && typeof a == "object") {
167
+ const n = {};
168
+ return Object.keys(a).forEach((o) => {
169
+ const c = a[o];
170
+ O.isBigNumber(c) ? n[o] = c.toHexString() : n[o] = c;
171
+ }), n;
176
172
  }
177
- return o;
173
+ return a;
178
174
  }
179
175
  }
180
- const b = /* @__PURE__ */ new Map(), A = /* @__PURE__ */ new Map();
181
- function J(t, n, e) {
182
- const o = b.get(t);
183
- if (!e && o)
176
+ const v = /* @__PURE__ */ new Map(), D = /* @__PURE__ */ new Map();
177
+ function J(r, t, e) {
178
+ const a = v.get(r);
179
+ if (!e && a)
180
+ return a;
181
+ const n = `${r}-${e}`, o = D.get(n);
182
+ if (o)
184
183
  return o;
185
- const a = `${t}-${e}`, r = A.get(a);
186
- if (r)
187
- return r;
188
- const i = new z(n, e ? void 0 : T), c = new O(i);
189
- return e ? (console.log(`[getPermitUtilsInstance] Set cached provider utils for chain ${t}-${e}`, c), A.set(a, c)) : (console.log(`[getPermitUtilsInstance] Set cached chain utils for chain ${t}`, c), b.set(t, c)), c;
184
+ const c = new z(t, e ? void 0 : T), s = new x(c);
185
+ return e ? (console.log(`[getPermitUtilsInstance] Set cached provider utils for chain ${r}-${e}`, s), D.set(n, s)) : (console.log(`[getPermitUtilsInstance] Set cached chain utils for chain ${r}`, s), v.set(r, s)), s;
190
186
  }
191
- const X = [
187
+ const M = [
192
188
  {
193
189
  constant: !0,
194
190
  inputs: [],
@@ -202,50 +198,120 @@ const X = [
202
198
  payable: !1,
203
199
  stateMutability: "view",
204
200
  type: "function"
201
+ },
202
+ {
203
+ inputs: [],
204
+ name: "eip712Domain",
205
+ outputs: [
206
+ {
207
+ internalType: "bytes1",
208
+ name: "fields",
209
+ type: "bytes1"
210
+ },
211
+ {
212
+ internalType: "string",
213
+ name: "name",
214
+ type: "string"
215
+ },
216
+ {
217
+ internalType: "string",
218
+ name: "version",
219
+ type: "string"
220
+ },
221
+ {
222
+ internalType: "uint256",
223
+ name: "chainId",
224
+ type: "uint256"
225
+ },
226
+ {
227
+ internalType: "address",
228
+ name: "verifyingContract",
229
+ type: "address"
230
+ },
231
+ {
232
+ internalType: "bytes32",
233
+ name: "salt",
234
+ type: "bytes32"
235
+ },
236
+ {
237
+ internalType: "uint256[]",
238
+ name: "extensions",
239
+ type: "uint256[]"
240
+ }
241
+ ],
242
+ stateMutability: "view",
243
+ type: "function"
205
244
  }
206
245
  ];
207
- async function Z(t, n, e) {
208
- const o = x(t);
209
- return R(o, X, e).callStatic.name();
246
+ async function X(r, t, e) {
247
+ const a = $(r), o = await k(a, M, e).callStatic.eip712Domain();
248
+ return Z(o, t, r);
249
+ }
250
+ async function Z(r, t, e) {
251
+ const {
252
+ extensions: a,
253
+ ...n
254
+ } = r;
255
+ if (a.length > 0)
256
+ throw Error("Extensions not implemented");
257
+ if (n.chainId && t !== parseInt(n.chainId, 16))
258
+ throw Error(`ChainId mismatch. Received: '${n.chainId}', expected: '${t}'`);
259
+ if (n.verifyingContract && e.toLowerCase() !== n.verifyingContract.toLowerCase())
260
+ throw Error(`Address mismatch. Received: '${n.verifyingContract}', expected: '${e}'`);
261
+ return te(n);
210
262
  }
211
- const ee = {
212
- value: v,
263
+ const ee = ["name", "version", "chainId", "verifyingContract", "salt"];
264
+ function te(r) {
265
+ const t = parseInt(r.fields, 16);
266
+ return ee.reduce((e, a, n) => (t & 1 << n && (e[a] = r[a]), e), {});
267
+ }
268
+ async function ne(r, t, e) {
269
+ const a = $(r);
270
+ return k(a, M, e).callStatic.name();
271
+ }
272
+ const re = {
273
+ value: S,
213
274
  nonce: 0,
214
275
  deadline: w()
215
- }, te = {
276
+ }, ae = {
216
277
  allowed: !0,
217
278
  nonce: 0,
218
279
  expiry: w()
219
- }, D = {}, P = {
280
+ }, A = {}, g = {
220
281
  type: "unsupported"
221
282
  };
222
- async function Pe(t) {
283
+ async function Pe(r) {
223
284
  const {
224
- tokenAddress: n,
285
+ tokenAddress: t,
225
286
  chainId: e
226
- } = t, o = `${e}-${n.toLowerCase()}`, a = D[o];
227
- if (a)
228
- return a;
229
- const r = ne(t);
230
- return D[o] = r, r;
287
+ } = r, a = `${e}-${t.toLowerCase()}`, n = A[a];
288
+ if (n)
289
+ return n;
290
+ const o = oe(r);
291
+ return A[a] = o, o;
231
292
  }
232
- async function ne(t) {
293
+ async function oe(r) {
233
294
  const {
234
- spender: n,
295
+ spender: t,
235
296
  tokenAddress: e,
236
- tokenName: o,
237
297
  chainId: a,
238
- provider: r
239
- } = t, i = J(a, r), c = T.address;
240
- let l = o;
298
+ provider: n
299
+ } = r, o = J(a, n), c = T.address;
300
+ let s;
241
301
  try {
242
- l = await Z(e, a, r);
243
- } catch (s) {
244
- if (/ETIMEDOUT/.test(s) && !l)
302
+ s = await X(e, a, n);
303
+ } catch (i) {
304
+ console.debug(`[checkTokenIsPermittable] Couldn't fetch eip712domain for token ${e}`, i);
305
+ }
306
+ let l = s == null ? void 0 : s.name;
307
+ try {
308
+ l || (l = await ne(e, a, n));
309
+ } catch (i) {
310
+ if (/ETIMEDOUT/.test(i) && !l)
245
311
  return {
246
312
  error: "Failed to fetch token name from contract. RPC connection error"
247
313
  };
248
- console.debug(`[checkTokenIsPermittable] Couldn't fetch token name from the contract for token ${e}, using provided '${l}'`, s);
314
+ console.debug(`[checkTokenIsPermittable] Couldn't fetch token name from the contract for token ${e}, using provided '${l}'`, i);
249
315
  }
250
316
  if (!l)
251
317
  return {
@@ -253,27 +319,27 @@ async function ne(t) {
253
319
  };
254
320
  let d;
255
321
  try {
256
- d = await i.getTokenNonce(e, c);
257
- } catch (s) {
258
- return s === "nonce not supported" || s.message === "nonce is NaN" ? (console.debug(`[checkTokenIsPermittable] Not a permittable token ${e} - ${l}`, s?.message || s), {
259
- ...P,
322
+ d = await o.getTokenNonce(e, c);
323
+ } catch (i) {
324
+ return i === "nonce not supported" || i.message === "nonce is NaN" ? (console.debug(`[checkTokenIsPermittable] Not a permittable token ${e} - ${l}`, (i == null ? void 0 : i.message) || i), {
325
+ ...g,
260
326
  name: l
261
- }) : (console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${e} - ${l}`, s), {
262
- error: s.message || s.toString()
327
+ }) : (console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${e} - ${l}`, i), {
328
+ error: i.message || i.toString()
263
329
  });
264
330
  }
265
- let u;
266
- if (!q.has(e))
331
+ let u = s == null ? void 0 : s.version;
332
+ if (!q.has(e) && u === void 0)
267
333
  try {
268
- u = await i.getTokenVersion(e);
269
- } catch (s) {
270
- console.debug(`[checkTokenIsPermittable] Failed to get version for ${e} - ${l}`, s);
334
+ u = await o.getTokenVersion(e);
335
+ } catch (i) {
336
+ console.debug(`[checkTokenIsPermittable] Failed to get version for ${e} - ${l}`, i);
271
337
  }
272
338
  const m = {
273
339
  chainId: a,
274
- eip2612PermitUtils: i,
340
+ eip2612PermitUtils: o,
275
341
  nonce: d,
276
- spender: n,
342
+ spender: t,
277
343
  tokenAddress: e,
278
344
  tokenName: l,
279
345
  walletAddress: c,
@@ -283,19 +349,19 @@ async function ne(t) {
283
349
  return await _({
284
350
  ...m,
285
351
  type: "eip-2612",
286
- provider: r
352
+ provider: n
287
353
  });
288
- } catch (s) {
354
+ } catch (i) {
289
355
  try {
290
- return await oe(e, i) ? await _({
356
+ return await se(e, o) ? await _({
291
357
  ...m,
292
358
  type: "dai-like",
293
- provider: r
294
- }) : /invalid signature/.test(s) || s?.code === "UNPREDICTABLE_GAS_LIMIT" ? (console.debug(`[checkTokenIsPermittable] Token ${e} - ${l} might be permittable, but it's not supported for now. Reason:`, s?.reason), {
295
- ...P,
359
+ provider: n
360
+ }) : /invalid signature/.test(i) || (i == null ? void 0 : i.code) === "UNPREDICTABLE_GAS_LIMIT" ? (console.debug(`[checkTokenIsPermittable] Token ${e} - ${l} might be permittable, but it's not supported for now. Reason:`, i == null ? void 0 : i.reason), {
361
+ ...g,
296
362
  name: l
297
- }) : (console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${e} - ${l}`, s), {
298
- error: s.message || s.toString()
363
+ }) : (console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${e} - ${l}`, i), {
364
+ error: i.message || i.toString()
299
365
  });
300
366
  } catch (p) {
301
367
  return console.debug(`[checkTokenIsPermittable] Failed to estimate dai-like permit for ${e} - ${l}`, p), {
@@ -304,81 +370,81 @@ async function ne(t) {
304
370
  }
305
371
  }
306
372
  }
307
- async function _(t) {
373
+ async function _(r) {
308
374
  const {
309
- provider: n,
375
+ provider: t,
310
376
  chainId: e,
311
- walletAddress: o,
312
- tokenAddress: a,
313
- tokenName: r,
314
- type: i,
315
- version: c
316
- } = t, d = await (i === "eip-2612" ? re : ae)(t);
317
- return d ? (await n.estimateGas({
377
+ walletAddress: a,
378
+ tokenAddress: n,
379
+ tokenName: o,
380
+ type: c,
381
+ version: s
382
+ } = r, d = await (c === "eip-2612" ? ie : ce)(r);
383
+ return d ? (await t.estimateGas({
318
384
  data: d,
319
- from: o,
320
- to: a
321
- })).toNumber() > V[e] ? {
322
- type: i,
323
- version: c,
324
- name: r
385
+ from: a,
386
+ to: n
387
+ })).toNumber() > B[e] ? {
388
+ type: c,
389
+ version: s,
390
+ name: o
325
391
  } : {
326
- ...P,
327
- name: r
392
+ ...g,
393
+ name: o
328
394
  } : {
329
- ...P,
330
- name: r
395
+ ...g,
396
+ name: o
331
397
  };
332
398
  }
333
- async function re(t) {
399
+ async function ie(r) {
334
400
  const {
335
- eip2612PermitUtils: n,
401
+ eip2612PermitUtils: t,
336
402
  walletAddress: e,
337
- spender: o,
338
- nonce: a,
339
- chainId: r,
340
- tokenName: i,
341
- tokenAddress: c,
403
+ spender: a,
404
+ nonce: n,
405
+ chainId: o,
406
+ tokenName: c,
407
+ tokenAddress: s,
342
408
  version: l
343
- } = t;
344
- return N({
345
- eip2162Utils: n,
409
+ } = r;
410
+ return R({
411
+ eip2162Utils: t,
346
412
  callDataParams: [{
347
- ...ee,
413
+ ...re,
348
414
  owner: e,
349
- spender: o,
350
- nonce: a
351
- }, +r, i, c, l]
415
+ spender: a,
416
+ nonce: n
417
+ }, +o, c, s, l]
352
418
  });
353
419
  }
354
- async function oe(t, n) {
355
- return await n.getPermitTypeHash(t) === S;
420
+ async function se(r, t) {
421
+ return await t.getPermitTypeHash(r) === L;
356
422
  }
357
- async function ae(t) {
423
+ async function ce(r) {
358
424
  const {
359
- eip2612PermitUtils: n,
425
+ eip2612PermitUtils: t,
360
426
  tokenAddress: e,
361
- walletAddress: o,
362
- spender: a,
363
- nonce: r,
364
- chainId: i,
365
- tokenName: c,
427
+ walletAddress: a,
428
+ spender: n,
429
+ nonce: o,
430
+ chainId: c,
431
+ tokenName: s,
366
432
  version: l
367
- } = t;
368
- return await n.getPermitTypeHash(e) === S ? $({
369
- eip2162Utils: n,
433
+ } = r;
434
+ return await t.getPermitTypeHash(e) === L ? N({
435
+ eip2162Utils: t,
370
436
  callDataParams: [{
371
- ...te,
372
- holder: o,
373
- spender: a,
374
- nonce: r
375
- }, i, c, e, l]
437
+ ...ae,
438
+ holder: a,
439
+ spender: n,
440
+ nonce: o
441
+ }, c, s, e, l]
376
442
  }) : !1;
377
443
  }
378
444
  export {
379
445
  T as PERMIT_SIGNER,
380
- fe as checkIsCallDataAValidPermit,
381
- ge as generatePermitHook,
446
+ he as checkIsCallDataAValidPermit,
447
+ ye as generatePermitHook,
382
448
  J as getPermitUtilsInstance,
383
449
  Pe as getTokenPermitInfo,
384
450
  W as isSupportedPermitInfo
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cowprotocol/permit-utils",
3
- "version": "0.0.2",
3
+ "version": "0.1.1-RC.1",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "ethers": "^5.7.2",
package/types.d.ts CHANGED
@@ -38,7 +38,6 @@ export type BuildDaiLikePermitCallDataParams = BasePermitCallDataParams & {
38
38
  export type GetTokenPermitInfoParams = {
39
39
  spender: string;
40
40
  tokenAddress: string;
41
- tokenName?: string | undefined;
42
41
  chainId: number;
43
42
  provider: JsonRpcProvider;
44
43
  };
@@ -0,0 +1,13 @@
1
+ import type { JsonRpcProvider } from '@ethersproject/providers';
2
+ export declare function getEip712Domain(tokenAddress: string, chainId: number, provider: JsonRpcProvider): Promise<Eip712Domain>;
3
+ type Eip5267Return = {
4
+ fields: string;
5
+ name?: string;
6
+ version?: string;
7
+ chainId?: string;
8
+ verifyingContract?: string;
9
+ salt?: string;
10
+ extensions?: string[];
11
+ };
12
+ export type Eip712Domain = Omit<Eip5267Return, 'fields' | 'extensions'>;
13
+ export {};
@@ -1 +0,0 @@
1
- export declare function fixTokenName(tokenName: string): string;