Skip to content

enable hooks for fetching code behind solidity import statements #5

@serapath

Description

@serapath

@todo

  • enable hooks for fetching and caching code behind solidity import statements

I think we should make another module which imports/requires solc-js and many resolvers, and exports a compile function, which takes sourcecode and uses the correct resolvers, so users dont have to bother

maybe here is some resolver code

const compile = require('solc-js')

const resolve_http = async x => await fetch(x).then(r => r.text())
const resolve_swarm = require('resolve-swarm')

const output = await compile(sourceode, async (importpath) => await resolve_http (importpath))

async function compile (sourcecode, getContent) {
  const allimports = await getAllImports(sourcecode)
  const localSources = {}
  // e.g. runs 10x when 10 imports in sourcecode
  for (path of allimports) {
    if (isSwarm(path)) localSources[path] = await resolve_swarm (path)
    if (isHttp(path) localSources[path] = await resolve_http (path)
    // ...
  }
  const output = solcjs(sourcecode, localSources)
  // let localSources = [{
    // path: 'lib.sol',
    // content: 'library L { function f() internal returns (uint) { return 7; } }'
  // }];
  return output
}

const myDB = { } // maybe it looks like:

const sourcecode = `
  import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/a.sol';
  import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/b.sol';
  import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/c.sol';
  import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/d.sol';
  import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/e.sol';
  import 'lib1.sol'
  import 'lib2.sol'
  import 'lib3.sol'
  import 'lib4.sol'
  import 'lib5.sol'

  library OldLibrary {
      function someFunction(uint8 a) public returns(bool);
  }

  contract NewContract {
      function f(uint8 a) public returns (bool) {
          return OldLibrary.someFunction(a);
      }
  }`

test('sourcecode with 10 imports calls callback 10 times', function (t) {
  t.plan(10)
  const output = await compile(sourcecode, async (path) => {
    t.assert(true)
    console.log(path)
    var output
    if (myDB.contains(path)) output = await myDB.get(path)
    else output = new Promise(resolve => {
      resolver.import(path, null, ({ content }) => resolve(content)
    })
    return output
  })
})

/*
  'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/a.sol';
  'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/b.sol';
  'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/c.sol';
  'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/d.sol';
  'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/e.sol';
  'lib1.sol'
  'lib2.sol'
  'lib3.sol'
  'lib4.sol'
  'lib5.sol'
*/

const output = await compile(sourcecode, async (path) => 
    myDB.contains(path) ? await myDB.get(path) : await getImportContent(path)
)

// so "getImportContent(...)" is a replacement for
new Promise(resolve => resolver.import(path, null, ({ content }) => resolve(content))

readCallback function can't be a async function, because emscripten doesn't support it very well.

but I think another workaround is provided "getReadCallback" API.

example 1:

let readCallback = await getReadCallback(sourceCode);
let output = await compiler(sourceCode, readCallback);

example 2:

let localSources = [{
       path: 'lib.sol',
       content: 'library L { function f() internal returns (uint) { return 7; } }'
     }];
 
let readCallback = await getReadCallback(sourceCode, localSources);
let output = await compiler(sourceCode, readCallback);

https://github.com/ethereum-play/solc-js/pull/1/commits/1db7eb24755acf1446487e7693073e2ca1be7301#diff-3b8192acb0d491039ab68dea0b430bfcR62

https://github.com/ethereum-play/solc-js/pull/1/commits/1db7eb24755acf1446487e7693073e2ca1be7301#diff-3b8192acb0d491039ab68dea0b430bfcR39

about imports




keywords

  • combineSource
  • resolver
  • import parser

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions