UNPKG

@depay/web3-tokens-evm

Version:

JavaScript library providing basic functionalities to interact with web3 tokens.

1,037 lines (988 loc) 21.9 kB
import { request } from '@depay/web3-client-evm'; import Blockchains from '@depay/web3-blockchains'; import { ethers } from 'ethers'; var allowanceOnEVM = ({ blockchain, address, api, owner, spender })=>{ return request( { blockchain, address, api, method: 'allowance', params: [owner, spender], // no cache for allowance! }, ) }; var balanceOnEVM = async ({ blockchain, address, account, api, id })=>{ if (address == Blockchains[blockchain].currency.address) { return await request( { blockchain: blockchain, address: account, method: 'balance', }, ) } else { return await request( { blockchain: blockchain, address: address, method: 'balanceOf', api, params: id ? [account, id] : [account], }, ) } }; var decimalsOnEVM = ({ blockchain, address, api })=>{ return request({ blockchain, address, api, method: 'decimals', cache: 86400000, // 1 day }) }; var ERC1155 = [ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "account", "type": "address" }, { "indexed": true, "internalType": "address", "name": "operator", "type": "address" }, { "indexed": false, "internalType": "bool", "name": "approved", "type": "bool" } ], "name": "ApprovalForAll", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "operator", "type": "address" }, { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }, { "indexed": false, "internalType": "uint256[]", "name": "values", "type": "uint256[]" } ], "name": "TransferBatch", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "operator", "type": "address" }, { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "id", "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "TransferSingle", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "string", "name": "value", "type": "string" }, { "indexed": true, "internalType": "uint256", "name": "id", "type": "uint256" } ], "name": "URI", "type": "event" }, { "inputs": [ { "internalType": "address", "name": "account", "type": "address" }, { "internalType": "uint256", "name": "id", "type": "uint256" } ], "name": "balanceOf", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address[]", "name": "accounts", "type": "address[]" }, { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" } ], "name": "balanceOfBatch", "outputs": [ { "internalType": "uint256[]", "name": "", "type": "uint256[]" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "account", "type": "address" }, { "internalType": "address", "name": "operator", "type": "address" } ], "name": "isApprovedForAll", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }, { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "name": "safeBatchTransferFrom", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "uint256", "name": "id", "type": "uint256" }, { "internalType": "uint256", "name": "amount", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "name": "safeTransferFrom", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "operator", "type": "address" }, { "internalType": "bool", "name": "approved", "type": "bool" } ], "name": "setApprovalForAll", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } ], "name": "supportsInterface", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "id", "type": "uint256" } ], "name": "uri", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" } ]; var ERC20 = [ { constant: true, inputs: [], name: 'name', outputs: [{ name: '', type: 'string' }], payable: false, stateMutability: 'view', type: 'function', }, { constant: false, inputs: [ { name: '_spender', type: 'address' }, { name: '_value', type: 'uint256' }, ], name: 'approve', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function', }, { constant: true, inputs: [], name: 'totalSupply', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function', }, { constant: false, inputs: [ { name: '_from', type: 'address' }, { name: '_to', type: 'address' }, { name: '_value', type: 'uint256' }, ], name: 'transferFrom', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function', }, { constant: true, inputs: [], name: 'decimals', outputs: [{ name: '', type: 'uint8' }], payable: false, stateMutability: 'view', type: 'function', }, { constant: true, inputs: [{ name: '_owner', type: 'address' }], name: 'balanceOf', outputs: [{ name: 'balance', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function', }, { constant: true, inputs: [], name: 'symbol', outputs: [{ name: '', type: 'string' }], payable: false, stateMutability: 'view', type: 'function', }, { constant: false, inputs: [ { name: '_to', type: 'address' }, { name: '_value', type: 'uint256' }, ], name: 'transfer', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function', }, { constant: true, inputs: [ { name: '_owner', type: 'address' }, { name: '_spender', type: 'address' }, ], name: 'allowance', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function', }, { payable: true, stateMutability: 'payable', type: 'fallback' }, { anonymous: false, inputs: [ { indexed: true, name: 'owner', type: 'address' }, { indexed: true, name: 'spender', type: 'address' }, { indexed: false, name: 'value', type: 'uint256' }, ], name: 'Approval', type: 'event', }, { anonymous: false, inputs: [ { indexed: true, name: 'from', type: 'address' }, { indexed: true, name: 'to', type: 'address' }, { indexed: false, name: 'value', type: 'uint256' }, ], name: 'Transfer', type: 'event', }, ]; var WETH = [ { "constant": true, "inputs": [], "name": "name", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "guy", "type": "address" }, { "name": "wad", "type": "uint256" } ], "name": "approve", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [], "name": "totalSupply", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "src", "type": "address" }, { "name": "dst", "type": "address" }, { "name": "wad", "type": "uint256" } ], "name": "transferFrom", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "wad", "type": "uint256" } ], "name": "withdraw", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [], "name": "decimals", "outputs": [ { "name": "", "type": "uint8" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "", "type": "address" } ], "name": "balanceOf", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "symbol", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "dst", "type": "address" }, { "name": "wad", "type": "uint256" } ], "name": "transfer", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [], "name": "deposit", "outputs": [], "payable": true, "stateMutability": "payable", "type": "function" }, { "constant": true, "inputs": [ { "name": "", "type": "address" }, { "name": "", "type": "address" } ], "name": "allowance", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "payable": true, "stateMutability": "payable", "type": "fallback" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "src", "type": "address" }, { "indexed": true, "name": "guy", "type": "address" }, { "indexed": false, "name": "wad", "type": "uint256" } ], "name": "Approval", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "src", "type": "address" }, { "indexed": true, "name": "dst", "type": "address" }, { "indexed": false, "name": "wad", "type": "uint256" } ], "name": "Transfer", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "dst", "type": "address" }, { "indexed": false, "name": "wad", "type": "uint256" } ], "name": "Deposit", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "src", "type": "address" }, { "indexed": false, "name": "wad", "type": "uint256" } ], "name": "Withdrawal", "type": "event" } ]; const uriAPI = [{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]; const uriToName = (tokenURI)=>{ return new Promise((resolve)=>{ if(tokenURI.match(/^ipfs/)) { tokenURI = `https://ipfs.io/ipfs/${tokenURI.split('://')[1]}`; } fetch(tokenURI).then((response) => { if (response.ok) { return response.json() } resolve(); }) .then((responseJson) => { if(responseJson) { let name = responseJson.name; if(name){ resolve(name); } else { resolve(); } } }).catch(()=>resolve()); }) }; var nameOnEVM = ({ blockchain, address, api, id })=>{ if(id) { return new Promise((resolve)=>{ request({ blockchain, address, api: uriAPI, method: 'uri', params: [id] }).then((uri)=>{ uri = uri.match('0x{id}') ? uri.replace('0x{id}', id) : uri; uriToName(uri).then(resolve); }).catch((error)=>{ console.log('error', error); resolve(); }); }) } else { return request( { blockchain: blockchain, address: address, api, method: 'name', cache: 86400000, // 1 day }, ) } }; var symbolOnEVM = ({ blockchain, address, api })=>{ return request( { blockchain, address, api, method: 'symbol', cache: 86400000, // 1 day } ) }; let supported = ['ethereum', 'bsc', 'polygon', 'fantom', 'arbitrum', 'avalanche', 'gnosis', 'optimism', 'base', 'worldchain']; supported.evm = ['ethereum', 'bsc', 'polygon', 'fantom', 'arbitrum', 'avalanche', 'gnosis', 'optimism', 'base', 'worldchain']; supported.svm = []; function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } class Token { constructor({ blockchain, address, name, decimals, symbol }) { this.blockchain = blockchain; if(supported.evm.includes(this.blockchain)) { this.address = ethers.utils.getAddress(address); } else if(supported.svm.includes(this.blockchain)) { this.address = address; } this._name = name; this._decimals = decimals; this._symbol = symbol; } async decimals() { if(this._decimals) { return this._decimals } if (this.address == Blockchains.findByName(this.blockchain).currency.address) { this._decimals = Blockchains.findByName(this.blockchain).currency.decimals; return this._decimals } let decimals; try { if(supported.evm.includes(this.blockchain)) { decimals = await decimalsOnEVM({ blockchain: this.blockchain, address: this.address, api: Token[this.blockchain].DEFAULT }); } else if(supported.svm.includes(this.blockchain)) { } } catch (e) {} this._decimals = decimals; return decimals } async symbol() { if(this._symbol) { return this._symbol } if (this.address == Blockchains.findByName(this.blockchain).currency.address) { this._symbol = Blockchains.findByName(this.blockchain).currency.symbol; return this._symbol } let symbol; if(supported.evm.includes(this.blockchain)) { return await symbolOnEVM({ blockchain: this.blockchain, address: this.address, api: Token[this.blockchain].DEFAULT }) } else if(supported.svm.includes(this.blockchain)) ; this._symbol = symbol; return symbol } async name(args) { if(this._name) { return this._name } if (this.address == Blockchains.findByName(this.blockchain).currency.address) { this._name = Blockchains.findByName(this.blockchain).currency.name; return this._name } let name; if(supported.evm.includes(this.blockchain)) { return await nameOnEVM({ blockchain: this.blockchain, address: this.address, api: Token[this.blockchain].DEFAULT, id: _optionalChain([args, 'optionalAccess', _ => _.id]) }) } else if(supported.svm.includes(this.blockchain)) ; this._name = name; return name } async balance(account, id) { if(supported.evm.includes(this.blockchain)) { return await balanceOnEVM({ blockchain: this.blockchain, account, address: this.address, api: id ? Token[this.blockchain][1155] : Token[this.blockchain].DEFAULT, id }) } else if(supported.svm.includes(this.blockchain)) ; } async allowance(owner, spender) { if (this.address == Blockchains.findByName(this.blockchain).currency.address) { return ethers.BigNumber.from(Blockchains.findByName(this.blockchain).maxInt) } if(supported.evm.includes(this.blockchain)) { return await allowanceOnEVM({ blockchain: this.blockchain, address: this.address, api: Token[this.blockchain].DEFAULT, owner, spender }) } else if(supported.svm.includes(this.blockchain)) { return ethers.BigNumber.from(Blockchains.findByName(this.blockchain).maxInt) } } async BigNumber(amount) { const decimals = await this.decimals(); if(typeof(amount) != 'string') { amount = amount.toString(); } if(amount.match('e')) { amount = parseFloat(amount).toFixed(decimals).toString(); } const decimalsMatched = amount.match(/\.(\d+)/); if(decimalsMatched && decimalsMatched[1] && decimalsMatched[1].length > decimals) { amount = parseFloat(amount).toFixed(decimals).toString(); } return ethers.utils.parseUnits( amount, decimals ) } async readable(amount) { let decimals = await this.decimals(); let readable = ethers.utils.formatUnits(amount.toString(), decimals); readable = readable.replace(/\.0+$/, ''); return readable } } Token.BigNumber = async ({ amount, blockchain, address }) => { let token = new Token({ blockchain, address }); return token.BigNumber(amount) }; Token.readable = async ({ amount, blockchain, address }) => { let token = new Token({ blockchain, address }); return token.readable(amount) }; Token.ethereum = { DEFAULT: ERC20, ERC20: ERC20, 20: ERC20, 1155: ERC1155, WRAPPED: WETH, }; Token.bsc = { DEFAULT: ERC20, BEP20: ERC20, 20: ERC20, 1155: ERC1155, WRAPPED: WETH, }; Token.polygon = { DEFAULT: ERC20, ERC20: ERC20, 20: ERC20, 1155: ERC1155, WRAPPED: WETH, }; Token.fantom = { DEFAULT: ERC20, FTM20: ERC20, 20: ERC20, 1155: ERC1155, WRAPPED: WETH, }; Token.arbitrum = { DEFAULT: ERC20, ERC20: ERC20, 20: ERC20, 1155: ERC1155, WRAPPED: WETH, }; Token.avalanche = { DEFAULT: ERC20, ERC20: ERC20, ARC20: ERC20, 20: ERC20, 1155: ERC1155, WRAPPED: WETH, }; Token.gnosis = { DEFAULT: ERC20, ERC20: ERC20, 20: ERC20, 1155: ERC1155, WRAPPED: WETH, }; Token.optimism = { DEFAULT: ERC20, ERC20: ERC20, 20: ERC20, 1155: ERC1155, WRAPPED: WETH, }; Token.base = { DEFAULT: ERC20, ERC20: ERC20, 20: ERC20, 1155: ERC1155, WRAPPED: WETH, }; Token.worldchain = { DEFAULT: ERC20, ERC20: ERC20, 20: ERC20, 1155: ERC1155, WRAPPED: WETH, }; export { Token as default };