Skip to content

Commit

Permalink
feat(init-autoswap): bundle command to initialize autoswap
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Oct 31, 2019
1 parent 8c18e19 commit 4c5a146
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 49 deletions.
82 changes: 48 additions & 34 deletions lib/ag-solo/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,51 +27,55 @@ const sendJSON = (ws, obj) => {
};

export default async function bundle(insistIsBasedir, args) {
const { _: a, evaluate, once, output, 'ag-solo': agSolo } = parseArgs(args, {
boolean: ['once', 'evaluate'],
alias: {o: 'output', e: 'evaluate'},
const { _: a, evaluate, input, once, output, 'ag-solo': agSolo } = parseArgs(args, {
boolean: ['once', 'evaluate', 'input'],
alias: {o: 'output', e: 'evaluate', i: 'input'},
stopEarly: true,
});

const [mainModule, ...namePaths] = a;
if (!mainModule) {
console.error('You must specify a main module to bundle');
return 1;
}

if (!output && !evaluate) {
console.error(`You must specify at least one of '--output' or '--evaluate'`);
return 1;
}

const bundled = {};

const moduleFile = `${__dirname}/${mainModule}.js`;
await Promise.all([`main=${moduleFile}`, ...namePaths].map(async namePath => {
const match = namePath.match(/^([^=]+)=(.+)$/);
if (!match) {
throw Error(`${namePath} isn't NAME=PATH`);
const bundles = [];
if (input) {
const fileNames = a;
for (const fileName of fileNames) {
const contents = file.promises.readFile(fileName, 'utf-8');
bundles.push(JSON.parse(contents));
}
const name = match[1];
const filepath = match[2];
bundled[name] = await buildSourceBundle(filepath);
}));
} else {
const [mainModule, ...namePaths] = a;
if (!mainModule) {
console.error('You must specify a main module to bundle');
return 1;
}

const bundled = {};
let moduleFile = mainModule;
if (moduleFile[0] !== '.' && moduleFile[0] !== '/') {
moduleFile = `${__dirname}/${mainModule}.js`;
}
await Promise.all([`main=${moduleFile}`, ...namePaths].map(async namePath => {
const match = namePath.match(/^([^=]+)=(.+)$/);
if (!match) {
throw Error(`${namePath} isn't NAME=PATH`);
}
const name = match[1];
const filepath = match[2];
bundled[name] = await buildSourceBundle(filepath);
}));
bundles.push(bundled);

if (output) {
await fs.promises.writeFile(output, JSON.stringify(bundled));
if (output) {
await fs.promises.writeFile(output, JSON.stringify(bundled), 'utf-8');
}
}

if (!evaluate) {
return 0;
}
const actualSources = `(${bundled.main.source}\n)\n${bundled.main.sourceMap}`;
// console.log(actualSources);
const mainNS = evaluateProgram(actualSources, { require })();
const main = mainNS.default;
if (typeof main !== 'function') {
console.error(`Bundle main does not have an export default function`);
return 1;
}

let wsurl = agSolo;
if (!agSolo) {
Expand Down Expand Up @@ -116,14 +120,24 @@ export default async function bundle(insistIsBasedir, args) {
if (await bootC.G.READY.M.isReady().P) {
console.error('Singleton bundle already installed');
ws.close();
exit.res(0);
exit.res(1);
return;
}
}

console.error(`Running bundle main entry point...`);
await main({ bundle: bundled, home: bootC.P });
console.error('Success!');
for (const bundled of bundles) {
const actualSources = `(${bundled.main.source}\n)\n${bundled.main.sourceMap}`;
// console.log(actualSources);
const mainNS = evaluateProgram(actualSources, { require })();
const main = mainNS.default;
if (typeof main !== 'function') {
console.error(`Bundle main does not have an export default function`);
continue;
}

await main({ bundle: bundled, home: bootC.P });
}
console.error('Done!');
if (once) {
await bootC.G.READY.M.resolve('initialized').P;
}
Expand Down
42 changes: 42 additions & 0 deletions lib/ag-solo/init-autoswap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import harden from '@agoric/harden';
import { upload } from './upload-contract';

// Usage:
// ag-solo bundle -e init-autoswap zoe:autoswap=../node_modules/@agoric/ertp/core/zoe/contracts/autoswap.js

export default async ({ home, bundle }) => {
// Install all the bundle entries that have a TARGET:NAME.
// TARGET may be 'zoe' or 'contractHost' for example.
const keyNames = Object.keys(bundle).sort().reduce((prior, key) => {
const match = key.match(/^[^:]+:(.*)/);
if (match) {
prior.push([key, match[1]]);
}
return prior;
}, []);
await upload(home, bundle, keyNames.map(([k, n]) => k));

// Register the installations.
const nameIds = {};
let autoswapKey;
await Promise.all(keyNames.map(([k, n]) =>
n === 'autoswap' ? autoswapKey = k : home~.uploads~.get(k).then(u => home~.registrar~.register(n, u))
.then(id => nameIds[n] = id)));

// TODO: This is just a sketch of how we might convert home.moolaMint into
// funds for the autoswap instance.

// Instantiate autoswap with some fresh moola and register the instance.
if (autoswapKey) {
const installHandle = await home~.uploads~.get(autoswapKey);
const options = {
assays: await Promise.all([home~.moolaMint~.getAssay()]),
purses: await Promise.all([home~.moolaMint~.mint(100000)]),
};
const instance = home~.zoe~.makeInstance(installHandle, harden(options));
nameIds['autoswap'] = await home~.registrar~.register('autoswap', instance);
}

// Output the record from contract IDs to registered names to stdout.
console.log(JSON.stringify(nameIds, undefined, 2));
};
17 changes: 16 additions & 1 deletion lib/ag-solo/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { deliver, addDeliveryTarget } from './outbound';
import { makeHTTPListener } from './web';

import { connectToChain } from './chain-cosmos-sdk';
import bundle from './bundle';

// import { makeChainFollower } from './follower';
// import { makeDeliverator } from './deliver-with-ag-cosmos-helper';
Expand Down Expand Up @@ -236,5 +237,19 @@ export default async function start(basedir, withSES, argv) {

console.log(`swingset running`);

// FIXME: Install the bundles as specified.
// Install the bundles as specified.
const initDir = path.join(basedir, 'init-bundles');
let list = [];
try {
list = await fs.promises.readdir(initDir);
} catch (e) {

}
for (const initName of list.sort()) {
console.log('loading init bundle', initName);
const initFile = path.join(initDir, initName);
if (await bundle(() => '.', ['--evaluate', '--once', '--input', initFile])) {
return 0;
}
}
}
12 changes: 7 additions & 5 deletions lib/ag-solo/upload-contract.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
export default async function installContracts({ home, bundle }) {
export default async function uploadContracts({ home, bundle }) {
console.error(`Installing targeted contracts...`);
await install(home, bundle, Object.keys(bundle).filter(k => k !== 'main').sort());
await upload(home, bundle, Object.keys(bundle).filter(k => k !== 'main').sort(), true);
}

export async function install(homeP, bundle, keys) {
export async function upload(homeP, bundle, keys, verbose = false) {
const names = [];
const contractsAP = [];
for (const key of keys) {
const match = key.match(/^(([^:]+):[^=]+)$/);
const match = key.match(/^(([^:]+):.+)$/);
if (!match) {
throw Error(`${key} isn't TARGET:NAME`);
}
Expand All @@ -23,7 +23,9 @@ export async function install(homeP, bundle, keys) {
);
} else {
// Install the contract, then save it in home.uploads.
console.log(name)
if (verbose) {
console.log(name);
}
contractsAP.push(targetObj~.install(source, moduleFormat));
names.push(name);
}
Expand Down
11 changes: 6 additions & 5 deletions lib/ag-solo/vats/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ export default function setup(syscall, state, helpers) {
syscall,
state,
(E, D) => {
async function createPrivateBundle(vats) {
async function createPrivateBundle(vats, exposeMint) {
return harden({
uploads: await E(vats.uploads).getUploads(),
moolaMint: await E(vats.moola).getMint(),
});
}

Expand All @@ -58,18 +59,18 @@ export default function setup(syscall, state, helpers) {

function makeBundler(contractHost, vats) {
return harden({
async createDemoBundle(nickname) {
async createDemoBundle(nickname, jackpot) {
const sharingService = await E(vats.sharing).getSharingService();
const registrar = await E(vats.registrar).getSharedRegistrar();
const chainTimerService = await E(vats.timer).createTimerService();
const pixelBundle = await E(vats.pixel).createPixelBundle(nickname);
const moolah = await E(vats.moolah).getSomeMoolah(nickname);
const moola = await E(vats.moola).getSomeMoola(nickname, jackpot);
const zoe = await E(vats.zoe).getZoe();
return harden({
...pixelBundle,
chainTimerService,
sharingService,
moolah,
moola,
contractHost,
registrar,
zoe,
Expand Down Expand Up @@ -211,7 +212,7 @@ export default function setup(syscall, state, helpers) {
await setupCommandDevice(vats, devices, { client: true });
await E(vats.http).setPresences(
bundle,
await createPrivateBundle(vats),
await createPrivateBundle(vats, true),
);
} else {
throw new Error(`ROLES was not recognized: ${ROLES}`);
Expand Down
12 changes: 8 additions & 4 deletions lib/ag-solo/vats/vat-moolah.js → lib/ag-solo/vats/vat-moola.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import { makeMint } from '@agoric/ertp/core/mint';
// This vat contains the registrar for the demo.

function build(E, log) {
const sharedMoolahMint = makeMint('moolah');
const sharedMoolaMint = makeMint('moola');

function getSomeMoolah(nickname) {
return sharedMoolahMint.mint(1000, `${nickname}'s moolah purse`);
function getSomeMoola(nickname, jackpot) {
return sharedMoolaMint.mint(1000, `${nickname}'s moola purse`);
}

return harden({ getSomeMoolah });
function getMint() {
return sharedMoolaMint;
}

return harden({ getSomeMoola, getMint });
}

export default function setup(syscall, state, helpers) {
Expand Down

0 comments on commit 4c5a146

Please sign in to comment.