-
Notifications
You must be signed in to change notification settings - Fork 205
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(contracts): upload to contractHost
ag-solo upload-contract can be used separately, but by default all contracts in BASEDIR/contracts/contract-* are bundled and uploaded to the newly-created contractHost.
- Loading branch information
1 parent
c8337f9
commit f9e7b5e
Showing
14 changed files
with
349 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { rollup } from 'rollup'; | ||
import path from 'path'; | ||
import resolve from 'rollup-plugin-node-resolve'; | ||
import acornEventualSend from '@agoric/acorn-eventual-send'; | ||
|
||
const DEFAULT_MODULE_FORMAT = 'getExport'; | ||
|
||
export default async function bundleSource( | ||
startFilename, | ||
moduleFormat = DEFAULT_MODULE_FORMAT, | ||
) { | ||
const resolvedPath = path.resolve(startFilename); | ||
const bundle = await rollup({ | ||
input: resolvedPath, | ||
treeshake: false, | ||
external: ['@agoric/evaluate', '@agoric/nat', '@agoric/harden'], | ||
plugins: [resolve()], | ||
acornInjectPlugins: [acornEventualSend()], | ||
}); | ||
const { output } = await bundle.generate({ | ||
exports: 'named', | ||
format: moduleFormat === 'getExport' ? 'cjs' : moduleFormat, | ||
}); | ||
if (output.length !== 1) { | ||
throw Error('unprepared for more than one chunk/asset'); | ||
} | ||
if (output[0].isAsset) { | ||
throw Error(`unprepared for assets: ${output[0].fileName}`); | ||
} | ||
let { code: source } = output[0]; | ||
|
||
// 'source' is now a string that contains a program, which references | ||
// require() and sets module.exports . This is close, but we need a single | ||
// stringifiable function, so we must wrap it in an outer function that | ||
// returns the exports. | ||
// | ||
// build-kernel.js will prefix this with 'export default' so it becomes an | ||
// ES6 module. The Vat controller will wrap it with parenthesis so it can | ||
// be evaluated and invoked to get at the exports. | ||
|
||
const sourceMap = `//# sourceURL=${resolvedPath}\n`; | ||
if (moduleFormat === 'getExport') | ||
source = `\ | ||
function getExport() { \ | ||
let exports = {}; \ | ||
const module = { exports }; \ | ||
\ | ||
${source} | ||
return module.exports; | ||
} | ||
`; | ||
|
||
return { source, sourceMap, moduleFormat }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export default harden((_terms, inviteMaker) => { | ||
const result = makePromise(); | ||
const seat = harden({ | ||
provide(n) { | ||
result.res(2 * n); | ||
}, | ||
result() { | ||
return result.p; | ||
}, | ||
}); | ||
return harden({ | ||
seat: inviteMaker.make('multiplicand', seat), | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { encourage } from './encourage'; | ||
|
||
export default harden((_terms, _inviteMaker) => { | ||
return harden({ | ||
encourageMe(name) { | ||
// log(`=> encouragementBot.encourageMe got the name: ${name}`); | ||
return encourage(name); | ||
}, | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const encourage = name => `${name}, you are awesome, keep it up!`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/* eslint-disable no-await-in-loop */ | ||
import parseArgs from 'minimist'; | ||
import WebSocket from 'ws'; | ||
import { E } from '@agoric/eventual-send'; | ||
import makeCapTP from '@agoric/captp'; | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
|
||
import buildSourceBundle from './build-source-bundle'; | ||
|
||
const makePromise = () => { | ||
const pr = {}; | ||
pr.p = new Promise((resolve, reject) => { | ||
pr.res = resolve; | ||
pr.rej = reject; | ||
}); | ||
return pr; | ||
}; | ||
|
||
const sendJSON = (ws, obj) => { | ||
if (ws.readyState !== ws.OPEN) { | ||
return; | ||
} | ||
// console.log('sending', obj); | ||
ws.send(JSON.stringify(obj)); | ||
}; | ||
|
||
export default async function upload(basedir, args) { | ||
const { _: namePaths, 'ag-solo': agSolo } = parseArgs(args, { | ||
stopEarly: true, | ||
}); | ||
if (namePaths.length === 0) { | ||
console.error('You must specify NAME=PATH pairs to upload'); | ||
return 1; | ||
} | ||
|
||
let wsurl = agSolo; | ||
if (!agSolo) { | ||
const cjson = await fs.promises.readFile( | ||
path.join(basedir, 'connections.json'), | ||
); | ||
for (const conn of JSON.parse(cjson)) { | ||
if (conn.type === 'http') { | ||
wsurl = `ws://${conn.host}:${conn.port}/captp`; | ||
} | ||
} | ||
} | ||
|
||
const ws = new WebSocket(wsurl); | ||
const exit = makePromise(); | ||
ws.on('open', async () => { | ||
try { | ||
const [handler, bootstrap] = makeCapTP('upload', obj => | ||
sendJSON(ws, obj), | ||
); | ||
ws.on('message', data => { | ||
// console.log(data); | ||
try { | ||
const obj = JSON.parse(data); | ||
if (obj.type === 'CTP_ERROR') { | ||
throw obj.error; | ||
} | ||
handler[obj.type](obj); | ||
} catch (e) { | ||
console.log('server error processing message', data, e); | ||
exit.rej(e); | ||
} | ||
}); | ||
|
||
let bootC; | ||
for (;;) { | ||
bootC = E.C(bootstrap()); | ||
if (!(await bootC.G.LOADING.P)) { | ||
break; | ||
} | ||
console.log(`waiting for chain to become ready`); | ||
await new Promise(resolve => setTimeout(resolve, 3000)); | ||
} | ||
|
||
const ids = await Promise.all( | ||
namePaths.map(async namePath => { | ||
const match = namePath.match(/^([^=]+)=(.+)$/); | ||
if (!match) { | ||
throw Error(`${namePath} isn't NAME=PATH`); | ||
} | ||
const name = match[1]; | ||
const path = match[2]; | ||
const { source, moduleFormat } = await buildSourceBundle(path); | ||
// console.log(`Uploading ${source}`); | ||
|
||
return bootC.G.contractHost.M.install(source, moduleFormat).P.then( | ||
res => bootC.G.registry.M.set(name, res).P, | ||
); | ||
}), | ||
); | ||
|
||
console.log('Success!'); | ||
setTimeout( | ||
() => | ||
console.log(`\ | ||
To create a contract instance, use: | ||
home.registry~.get(ID)~.spawn(TERMS) | ||
where ID is the registered installation id, one of: | ||
${ids.join('\n ')}`), | ||
1000, | ||
); | ||
ws.close(); | ||
exit.res(0); | ||
} catch (e) { | ||
exit.rej(e); | ||
} | ||
}); | ||
ws.on('close', (_code, _reason) => { | ||
console.log('connection closed'); | ||
exit.res(1); | ||
}); | ||
return exit.p; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.