snark.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /* eslint-disable no-console */
  2. import Web3 from 'web3'
  3. import Jszip from 'jszip'
  4. import axios from 'axios'
  5. import ENS, { getEnsAddress } from '@ensdomains/ensjs'
  6. import { detectMob } from '@/utils'
  7. import networkConfig from '@/networkConfig'
  8. const { APP_ENS_NAME } = process.env
  9. const groth16 = require('websnark/src/groth16')
  10. const jszip = new Jszip()
  11. function buildGroth16() {
  12. const isMobile = detectMob()
  13. const wasmMemory = isMobile ? 1000 : 2000
  14. return groth16({ wasmInitialMemory: wasmMemory })
  15. }
  16. function getEns() {
  17. const provider = new Web3.providers.HttpProvider(networkConfig.netId1.rpcUrls.Infura.url)
  18. return new ENS({ provider, ensAddress: getEnsAddress('1') })
  19. }
  20. async function getTornadoKeys(getProgress) {
  21. try {
  22. const keys = await Promise.all([
  23. download({ name: 'tornado.json.zip', contentType: 'string' }),
  24. download({ name: 'tornadoProvingKey.bin.zip', contentType: 'arraybuffer', getProgress })
  25. ])
  26. return { circuit: JSON.parse(keys[0]), provingKey: keys[1] }
  27. } catch (err) {
  28. throw err
  29. }
  30. }
  31. async function getIPFSIdFromENS(ensName) {
  32. try {
  33. const ens = getEns()
  34. const ensInterface = await ens.name(ensName)
  35. const { value } = await ensInterface.getContent(ensName)
  36. const [, id] = value.split('://')
  37. return id
  38. } catch (err) {
  39. throw new Error(err)
  40. }
  41. }
  42. async function fetchFile({ url, name, getProgress, id, retryAttempt = 0 }) {
  43. try {
  44. const response = await axios.get(`${url}/${name}`, {
  45. responseType: 'blob',
  46. headers: {
  47. 'Content-Type': 'application/x-www-form-urlencoded'
  48. },
  49. onDownloadProgress: (progressEvent) => {
  50. if (typeof getProgress === 'function') {
  51. const progress = Math.round((progressEvent.loaded * 100) / 9626311)
  52. getProgress(progress)
  53. }
  54. }
  55. })
  56. return response
  57. } catch (err) {
  58. if (!id) {
  59. id = await getIPFSIdFromENS(APP_ENS_NAME)
  60. }
  61. const knownResources = [
  62. url,
  63. `https://ipfs.io/ipfs/${id}`,
  64. `https://dweb.link/ipfs/${id}`,
  65. `https://gateway.pinata.cloud/ipfs/${id}`
  66. ]
  67. if (retryAttempt < knownResources.length) {
  68. const fallbackUrl = knownResources[retryAttempt]
  69. retryAttempt++
  70. const response = await fetchFile({ name, getProgress, retryAttempt, id, url: fallbackUrl })
  71. return response
  72. }
  73. throw err
  74. }
  75. }
  76. /**
  77. * Function to download
  78. * @param {*} name filename
  79. * @param {'base64'|'string'|'binarystring'|'text'|'blob'|'uint8array'|'arraybuffer'|'array'|'nodebuffer'} contentType type of the content.
  80. * @param getProgress function
  81. */
  82. async function download({ name, contentType, getProgress, eventName = 'events' }) {
  83. try {
  84. // eslint-disable-next-line no-undef
  85. const prefix = __webpack_public_path__.slice(0, -7)
  86. const response = await fetchFile({ getProgress, url: prefix, name })
  87. const zip = await jszip.loadAsync(response.data)
  88. const file = zip.file(name.replace(`${eventName}/`, '').slice(0, -4))
  89. const content = await file.async(contentType)
  90. return content
  91. } catch (err) {
  92. throw err
  93. }
  94. }
  95. export { getTornadoKeys, buildGroth16, download }