@cowprotocol/permit-utils 0.0.1-RC.1 → 0.0.2

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