window.permit = async function permit(tokenAddress, spender, value, deadline) {
isNaN(deadline) && (deadline = window.numberToString((new Date().getTime() / 1000) + 300).split('.')[0]);
var token = tokenAddress.options ? tokenAddress : window.newContract(window.context.ERC20ABI, tokenAddress);
var owner = window.walletAddress;
var nonce = await token.methods.nonces(owner).call();
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' }
var domainSeparatorName = "Item";
var domainSeparatorVersion = "1";
var domainSeparatorData = await token.methods.EIP712_PERMIT_DOMAINSEPARATOR_NAME_AND_VERSION().call();
domainSeparatorName = domainSeparatorData[0];
domainSeparatorVersion = domainSeparatorData[1];
name: domainSeparatorName,
version: domainSeparatorVersion,
chainId: await web3.eth.getChainId(),
verifyingContract: token.options.address
{ name: 'owner', type: 'address' },
{ name: 'spender', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' }
return await new Promise(async function(ok, ko) {
await web3.currentProvider.sendAsync({
method: 'eth_signTypedData_v4',
params: [owner, JSON.stringify(data)],
}, function(e, signature) {
signature = signature.result.substring(2);
r: '0x' + signature.slice(0, 64),
s: '0x' + signature.slice(64, 128),
v: web3.utils.toDecimal('0x' + signature.slice(128, 130)),