@neo-one/server-plugin-wallet
Version:
NEO•ONE Server wallet plugin.
681 lines (680 loc) • 102 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const client_common_1 = require("@neo-one/client-common");
const client_core_1 = require("@neo-one/client-core");
const client_full_core_1 = require("@neo-one/client-full-core");
const server_plugin_network_1 = require("@neo-one/server-plugin-network");
const smart_contract_compiler_1 = require("@neo-one/smart-contract-compiler");
const smart_contract_compiler_node_1 = require("@neo-one/smart-contract-compiler-node");
const utils_1 = require("@neo-one/utils");
const bignumber_js_1 = tslib_1.__importDefault(require("bignumber.js"));
const fs = tslib_1.__importStar(require("fs-extra"));
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const ora_1 = tslib_1.__importDefault(require("ora"));
const path = tslib_1.__importStar(require("path"));
const rxjs_1 = require("rxjs");
const constants_1 = require("./constants");
const DEFAULT_NUM_WALLETS = 10;
exports.DEFAULT_MASTER_PRIVATE_KEY = '9e9522c90f4b33cac8a174353ae54651770f3f4dd1de78e74d9b49ba615d7c1f';
const DEFAULT_MASTER_PUBLIC_KEY = '03396d8a87f1f77be1ca1e2d63ee3c1a642a9c45d3fb1dc2bfdd7ce680043244f2';
const DEFAULT_NETWORK_NAME = 'priv';
exports.DEFAULT_PRIVATE_KEY_AND_PUBLIC_KEYS = [
[
'e35ecb8189067a0a06f17f163be3db95c4b7805c81b48af1f4b8bbdfbeeb1afd',
'020266f0d31fa8c1c28cfe8712cc26b6d41ff910deb02341dfe628573178906940',
],
[
'6cad314f75624a26b780368a8b0753d10815ca44c1fca6eb3972484548805d9e',
'02eae8da9a7f159395efb1789fe18134521b5c21315ca216e65f430c8f0a934957',
],
[
'e91dc6e5fffcae0510ef5a7e41675d024e5b286769b3ff455e71e01a4cf16ef0',
'02f6ed86ceb2cdd69fac03872e50860e853e3dbf9873bf3a2fb4313d4366fabf1b',
],
[
'fa38cb00810d173e14631219d8ee689ee183a3d307c3c8bd2e1234d332dd3255',
'022987fb75e1b64bae89b96a3efc978c0562987a7e718071bda2be5e28111534be',
],
[
'3ca9e1140253f75dded54a1e73bfd44678d0cbf7b9ee7229dfa2cf06aba6a3b5',
'02ff4132c82500232c1bc75747e370fa5f4313417213f9896388c259825cc23e3d',
],
[
'3cdafff958a81f84425b062085aad7a842fd35d980f873aee392116cdd10969d',
'0244df8a470957db89cd7b8e3b58c43429b789c3eae8000ed425a9a4e117752e52',
],
[
'48e297109c2a9d46a9f72ad9bcf71ad784e2613695b9455dc1b1a3295955c774',
'03016acb92193f545572b990e43877eefa0a70a22cfba3516bd853c8f301d3a6ae',
],
[
'996b7ff875733a4b4aa92f450923bf64ee0f1b9d8c88028d06cef808221f2fb2',
'037ddc19798d79f99a2ecbd6d0232b9272a15b3e11f18a7e267be5a8cb5e1f27ed',
],
[
'eeb0940129baed17ae519a228afed2664a7bce372df0885a2675ee4426151a0f',
'02ff73b451d289e11d25b503590442dea87227f0eb19b766fdbc158e6ce4e17a24',
],
[
'31efd094e0e299daaae8e08c1f7e99df0d71f8f26b30924274901812a4730992',
'036c6d633f38ebb5be31784031d065bae11cdba2999186c896366ebccf3efe538b',
],
];
exports.DEFAULT_PRIVATE_KEYS = exports.DEFAULT_PRIVATE_KEY_AND_PUBLIC_KEYS.map(([key]) => key);
exports.ASSET_INFO = [
{
type: 'Token',
name: 'redcoin',
amount: new bignumber_js_1.default(1000000),
precision: 4,
privateKey: '7bb05e6087cd116aa5f1da9001736a5350981c4548116e2bc08c9a4f29b3fee4',
publicKey: '024ec7428c134451d741383f2ea1c61a92159b072d517e3f8a1a8a6ef1a63948c3',
},
{
type: 'Token',
name: 'bluecoin',
amount: new bignumber_js_1.default(660000),
precision: 0,
privateKey: 'c27b96a2854ead7d4b4ef50de2695201fef87d3d46c9b36a6cd113774706748b',
publicKey: '02e530f413e225e6b0b179e43a18e0676c724486f3c582eb1e78b2f799b38cdd68',
},
{
type: 'Currency',
name: 'greencoin',
amount: new bignumber_js_1.default(50000000),
precision: 6,
privateKey: '8868b8c6152e3ba39e3c31b4774f67fcce3465f41720a408d59bfd34e6980ec3',
publicKey: '035a0afe8410cd5df818f9b2734ab64ecd59ed8aa8fb4c5e0257364296524e0c62',
},
];
exports.TOKEN_INFO = [
{
name: 'RedToken',
amount: new bignumber_js_1.default(1000000),
privateKey: '3fedc9048caf7b75cece9d0db85748e5cb44940ff4d48f6230526db295040df4',
publicKey: '024c8991bd84f8f08a96abe2f7be01dff4c65abde974c3ac99135451293b34961e',
},
{
name: 'BlueToken',
amount: new bignumber_js_1.default(660000),
privateKey: 'b29b677bf6c1abb7e184d943df10c3b57bedc14a85f9fda21cc93ec1b91be9ae',
publicKey: '039c4b0efe9b3dc35a138aad1d8f3a48dfe660b837379f39d49a50f0fc54ee0e0e',
},
{
name: 'GreenToken',
amount: new bignumber_js_1.default(50000000),
privateKey: 'b8ec5eb6c6f499240fc431bbf68feee76ef503212e61496f0c8b8804168ae954',
publicKey: '02a9f7d888a23c20a45621a504c5d716895e5fd8941c6d7620975101b46ae81527',
},
];
const getNetwork = async ({ cli, options }) => {
const { network: networkName } = options;
if (networkName != undefined && typeof networkName === 'string') {
return networkName;
}
const { network } = await cli.getSession(server_plugin_network_1.constants.PLUGIN);
if (network != undefined && typeof network === 'string') {
return network;
}
throw new Error('Bootstrap requires a network. Activate a network by ' +
'running `activate network <name>` or specify the network via ' +
'`--network <name>`');
};
async function getRPC({ options }) {
const { rpc } = options;
if (rpc != undefined && typeof rpc === 'string') {
if (rpc === server_plugin_network_1.constants.NETWORK_URL.MAIN || rpc === server_plugin_network_1.constants.NETWORK_URL.TEST) {
throw new Error('Invalid Network: Can only bootstrap a private network');
}
return rpc;
}
throw new Error('Bootstrap requires an input RPC URL to connect to the NEO Tracker private network');
}
const makeWallet = ({ networkName, wallet }) => {
if (wallet.wif === undefined) {
throw new Error(`Something went wrong, wif is null for ${wallet.name}`);
}
return {
name: wallet.name,
privateKey: client_common_1.wifToPrivateKey(wallet.wif),
accountID: {
network: networkName,
address: wallet.address,
},
};
};
async function getWallet({ walletName, networkName, cli, plugin, }) {
const wallet = await plugin.walletResourceType.getResource({
name: constants_1.constants.makeWallet({
network: networkName,
name: walletName,
}),
client: cli.client,
options: {},
});
if (wallet === undefined) {
throw new Error(`Something went wrong, could not get wallet ${walletName}`);
}
return makeWallet({ networkName, wallet });
}
async function createWallet({ walletName, networkName, cli, privateKey, }) {
const walletResource = await cli.client.createResource({
plugin: constants_1.constants.PLUGIN,
resourceType: constants_1.constants.WALLET_RESOURCE_TYPE,
name: constants_1.constants.makeWallet({ name: walletName, network: networkName }),
options: {
network: networkName,
privateKey,
},
cancel$: rxjs_1.of(),
});
const wallet = walletResource;
return makeWallet({ networkName, wallet });
}
function getNumWallets(options) {
let { wallets } = options;
if (wallets != undefined && typeof wallets !== 'number') {
throw new Error('--wallets <number> option must be a number');
}
if (wallets == undefined) {
wallets = DEFAULT_NUM_WALLETS;
}
return wallets % 2 === 0 ? wallets : wallets + 1;
}
async function createTransfers({ wallet, from, }) {
let neo;
let gas;
if (from === undefined) {
neo = new bignumber_js_1.default('1000000');
gas = new bignumber_js_1.default('1000000');
}
else {
neo = new bignumber_js_1.default('250000');
gas = new bignumber_js_1.default('250000');
}
return [
{
amount: neo,
asset: client_common_1.common.NEO_ASSET_HASH,
to: wallet.accountID.address,
},
{
amount: gas,
asset: client_common_1.common.GAS_ASSET_HASH,
to: wallet.accountID.address,
},
];
}
async function initializeWallets({ wallets, master, client, developerClient, }) {
const [firstWalletBatch, secondWalletBatch] = lodash_1.default.chunk(wallets, wallets.length / 2);
const firstTransferBatchRaw = await Promise.all(firstWalletBatch.map(async (wallet) => createTransfers({ wallet })));
const firstTransferBatch = lodash_1.default.flatten(firstTransferBatchRaw);
const firstTransactionBatch = await client.transfer(firstTransferBatch, {
from: master.accountID,
});
await Promise.all([developerClient.runConsensusNow(), firstTransactionBatch.confirmed()]);
const secondTransactionBatch = await Promise.all(utils_1.utils.zip(firstWalletBatch, secondWalletBatch).map(async ([from, wallet]) => client.transfer(await createTransfers({ wallet, from }), {
from: from.accountID,
})));
await Promise.all([
Promise.all(secondTransactionBatch.map(async (transaction) => transaction.confirmed())),
developerClient.runConsensusNow(),
]);
}
async function initiateClaims({ wallets, networkName, client, developerClient, provider, }) {
const unclaimed = await Promise.all(wallets.map(async (wallet) => provider.getUnclaimed(networkName, wallet.accountID.address)));
const unclaimedWallets = utils_1.utils
.zip(wallets, unclaimed)
.filter(([__, accountUnclaimed]) => accountUnclaimed.unclaimed.length > 0)
.map(([wallet]) => wallet);
const claims = await Promise.all(unclaimedWallets.map(async (wallet) => client.claim({ from: wallet.accountID })));
await Promise.all([developerClient.runConsensusNow(), Promise.all(claims.map(async (claim) => claim.confirmed()))]);
}
async function setupWallets({ wallets, client, developerClient, master, }) {
const startingGAS = new bignumber_js_1.default(50000);
const transfer = await client.transfer(wallets.map((wallet) => ({
amount: startingGAS,
asset: client_common_1.common.GAS_ASSET_HASH,
to: wallet.accountID.address,
})), { from: master.accountID });
await Promise.all([developerClient.runConsensusNow(), transfer.confirmed()]);
}
async function registerAssets({ assetWallets, client, developerClient, }) {
const assetRegistrations = await Promise.all(utils_1.utils.zip(exports.ASSET_INFO, assetWallets).map(async ([asset, wallet]) => client.registerAsset({
type: asset.type,
name: asset.name,
amount: asset.amount,
precision: asset.precision,
owner: client_common_1.privateKeyToPublicKey(wallet.privateKey),
admin: wallet.accountID.address,
issuer: wallet.accountID.address,
}, {
from: wallet.accountID,
})));
const [registrations] = await Promise.all([
Promise.all(assetRegistrations.map(async (registration) => registration.confirmed())),
developerClient.runConsensusNow(),
]);
const assetHashes = registrations.filter(Boolean).map((registration) => {
if (registration.result.state === 'FAULT') {
throw new Error(registration.result.message);
}
return registration.result.value.hash;
});
return utils_1.utils.zip(exports.ASSET_INFO, assetWallets, assetHashes).map((asset) => (Object.assign({}, asset[0], { wallet: asset[1], hash: asset[2] })));
}
async function issueAsset({ asset, client, }) {
const transfer = {
to: asset.wallet.accountID.address,
asset: asset.hash,
amount: asset.amount,
};
return client.issue([transfer], {
from: asset.wallet.accountID,
});
}
const issueAssets = async ({ assets, client, developerClient, }) => {
const issues = await Promise.all(assets.map(async (asset) => issueAsset({ asset, client })));
await Promise.all([developerClient.runConsensusNow(), Promise.all(issues.map(async (issue) => issue.confirmed()))]);
};
async function createAssetTransfer({ wallets, asset, client, }) {
const transfers = wallets.map((wallet) => ({
to: wallet.accountID.address,
asset: asset.hash,
amount: asset.amount
.div(2)
.div(wallets.length)
.integerValue(bignumber_js_1.default.ROUND_FLOOR),
}));
return client.transfer(transfers, {
from: asset.wallet.accountID,
});
}
const transferAssets = async ({ wallets, assets, client, developerClient, }) => {
const assetTransfers = await Promise.all(assets.map(async (asset, idx) => createAssetTransfer({
wallets: idx % 2 === 0 ? wallets.slice(0, wallets.length / 2) : wallets.slice(wallets.length / 2),
asset,
client,
})));
await Promise.all([
developerClient.runConsensusNow(),
Promise.all(assetTransfers.map(async (transfer) => transfer.confirmed())),
]);
};
const getAssetWallets = (networkName) => exports.ASSET_INFO.map(({ name, privateKey }) => ({
name: `${name}-wallet`,
privateKey,
accountID: {
network: networkName,
address: client_common_1.privateKeyToAddress(privateKey),
},
}));
const getTokenWallets = (networkName) => exports.TOKEN_INFO.map(({ name, privateKey }) => ({
name: `${name}-token-wallet`,
privateKey,
accountID: {
network: networkName,
address: client_common_1.privateKeyToAddress(privateKey),
},
}));
async function getPresetData({ cliOptions, plugin, walletNames, }) {
const rpcURL = await getRPC(cliOptions);
const network = {
name: DEFAULT_NETWORK_NAME,
rpcURL,
};
let master;
if (cliOptions.args.options['testing-only']) {
master = await getWallet({
walletName: constants_1.constants.MASTER_WALLET,
networkName: network.name,
cli: cliOptions.cli,
plugin,
});
}
else {
client_common_1.crypto.addPublicKey(client_common_1.common.stringToPrivateKey(exports.DEFAULT_MASTER_PRIVATE_KEY), client_common_1.common.stringToECPoint(DEFAULT_MASTER_PUBLIC_KEY));
master = {
name: 'master',
privateKey: exports.DEFAULT_MASTER_PRIVATE_KEY,
accountID: {
network: network.name,
address: client_common_1.privateKeyToAddress(exports.DEFAULT_MASTER_PRIVATE_KEY),
},
};
}
const getHardCodedWallet = ([name, privateKey]) => ({
name,
privateKey,
accountID: {
network: network.name,
address: client_common_1.privateKeyToAddress(privateKey),
},
});
const getGeneratedWallet = (name) => {
const privateKey = client_common_1.createPrivateKey();
return {
name,
privateKey,
accountID: {
network: network.name,
address: client_common_1.privateKeyToAddress(privateKey),
},
};
};
exports.DEFAULT_PRIVATE_KEY_AND_PUBLIC_KEYS.forEach(([privateKey, publicKey]) => {
client_common_1.crypto.addPublicKey(client_common_1.common.stringToPrivateKey(privateKey), client_common_1.common.stringToECPoint(publicKey));
});
const wallets = utils_1.utils
.zip(walletNames.slice(0, exports.DEFAULT_PRIVATE_KEYS.length / 2), exports.DEFAULT_PRIVATE_KEYS.slice(0, exports.DEFAULT_PRIVATE_KEYS.length / 2))
.map(getHardCodedWallet)
.concat(walletNames.slice(exports.DEFAULT_PRIVATE_KEYS.length / 2, walletNames.length / 2).map(getGeneratedWallet))
.concat(utils_1.utils
.zip(walletNames.slice(walletNames.length / 2, walletNames.length / 2 + exports.DEFAULT_PRIVATE_KEYS.length / 2), exports.DEFAULT_PRIVATE_KEYS.slice(exports.DEFAULT_PRIVATE_KEYS.length / 2))
.map(getHardCodedWallet))
.concat(walletNames.slice(walletNames.length / 2 + exports.DEFAULT_PRIVATE_KEYS.length / 2).map(getGeneratedWallet));
return {
network,
master,
wallets,
assetWallets: getAssetWallets(network.name),
tokenWallets: getTokenWallets(network.name),
};
}
async function getNEOONEData({ cliOptions, plugin, walletNames, }) {
const networkName = await getNetwork(cliOptions);
if (networkName === server_plugin_network_1.constants.NETWORK_NAME.MAIN || networkName === server_plugin_network_1.constants.NETWORK_NAME.TEST) {
throw new Error('Invalid Network: Can only bootstrap a private network');
}
const networkResource = await cliOptions.cli.client.getResource({
plugin: server_plugin_network_1.constants.PLUGIN,
name: networkName,
resourceType: server_plugin_network_1.constants.NETWORK_RESOURCE_TYPE,
options: {},
});
if (networkResource === undefined) {
throw new Error(`Network ${networkName} does not exist.`);
}
const networkInfo = networkResource;
const network = {
name: networkInfo.name,
rpcURL: networkInfo.nodes[0].rpcAddress,
};
const master = await getWallet({
walletName: constants_1.constants.MASTER_WALLET,
networkName: network.name,
cli: cliOptions.cli,
plugin,
});
const wallets = await Promise.all(walletNames.map(async (walletName) => createWallet({
walletName,
networkName: network.name,
cli: cliOptions.cli,
})));
const assetWallets = await Promise.all(getAssetWallets(network.name).map(async (wallet) => createWallet({
walletName: wallet.name,
networkName: network.name,
cli: cliOptions.cli,
privateKey: wallet.privateKey,
})));
const tokenWallets = await Promise.all(getTokenWallets(network.name).map(async (wallet) => createWallet({
walletName: wallet.name,
networkName: network.name,
cli: cliOptions.cli,
privateKey: wallet.privateKey,
})));
return {
network,
master,
wallets,
assetWallets,
tokenWallets,
};
}
async function addWalletsToKeystore({ keystore, networkName, master, wallets, assetWallets, tokenWallets, }) {
await Promise.all(wallets
.concat([master])
.concat(assetWallets)
.concat(tokenWallets)
.map(async (wallet) => keystore.addUserAccount({
network: networkName,
name: wallet.name,
privateKey: wallet.privateKey,
})));
}
const findContracts = async (current) => {
const exists = await fs.pathExists(path.resolve(current, 'package.json'));
if (exists) {
return path.resolve(current, current.split(path.sep).some((dir) => dir === 'dist') ? '' : 'src', 'contracts');
}
return findContracts(path.dirname(current));
};
exports.compileSmartContract = async (contractName) => {
const dir = await findContracts(require.resolve('@neo-one/server-plugin-wallet'));
const result = smart_contract_compiler_1.compileContract(path.resolve(dir, `${contractName}.ts`), contractName, smart_contract_compiler_node_1.createCompilerHost());
const sourceMap = await result.sourceMap;
return Object.assign({}, result, { sourceMap });
};
const compileSmartContracts = async (contractNames) => Promise.all(contractNames.map(exports.compileSmartContract));
const publishContract = async ({ wallet, client, result: { contract }, }) => client.publish(contract, { from: wallet.accountID });
const publishTokens = async ({ tokenWallets, isRPC, client, developerClient, }) => {
const wallets = utils_1.utils.zip(tokenWallets, exports.TOKEN_INFO).map(([wallet, token]) => ({
wallet,
token,
}));
const compileResults = await compileSmartContracts(wallets.map(({ token }) => token.name));
const publishResults = await Promise.all(utils_1.utils.zip(wallets, compileResults).map(async ([{ wallet }, compileResult]) => publishContract({
wallet,
result: compileResult,
isRPC,
client,
})));
const [receipts] = await Promise.all([
Promise.all(publishResults.map(async (result) => result.confirmed())),
developerClient.runConsensusNow(),
]);
const tokenWithWallets = utils_1.utils
.zip(wallets, compileResults, receipts)
.map(([{ token, wallet }, compileResult, receipt]) => {
if (receipt.result.state === 'FAULT') {
throw new Error(receipt.result.message);
}
const address = receipt.result.value.address;
const smartContract = client.smartContract({
networks: {
[wallet.accountID.network]: { address },
},
abi: compileResult.abi,
sourceMaps: Promise.resolve({ [address]: compileResult.sourceMap }),
});
return Object.assign({}, token, { smartContract, wallet, hash: address });
});
const deployResults = await Promise.all(tokenWithWallets.map(({ smartContract, wallet, amount }) => smartContract.deploy(client_common_1.privateKeyToAddress(wallet.privateKey), amount, {
from: wallet.accountID,
})));
const [deployReceipts] = await Promise.all([
Promise.all(deployResults.map((result) => result.confirmed())),
developerClient.runConsensusNow(),
]);
deployReceipts.forEach((receipt) => {
if (receipt.result.state === 'FAULT') {
throw new Error(receipt.result.message);
}
});
return tokenWithWallets;
};
async function transferToken({ tokens, count, developerClient, }) {
const results = await Promise.all(tokens.map(([token, wallet]) => token.smartContract.transfer(client_common_1.privateKeyToAddress(token.wallet.privateKey), client_common_1.privateKeyToAddress(wallet.privateKey), token.amount
.div(2)
.div(count)
.integerValue(bignumber_js_1.default.ROUND_FLOOR), { from: token.wallet.accountID })));
await Promise.all([Promise.all(results.map((result) => result.confirmed())), developerClient.runConsensusNow()]);
}
const transferTokens = async ({ wallets, tokens, developerClient, }) => {
const count = wallets.length / 2;
const tokensWithWallets = tokens.map((token, idx) => [
token,
idx % 2 === 0 ? wallets.slice(0, count) : wallets.slice(count),
]);
for (const idx of lodash_1.default.range(count)) {
await transferToken({
tokens: tokensWithWallets.map(([token, tokenWallets]) => [token, tokenWallets[idx]]),
count,
developerClient,
});
}
};
exports.bootstrap = (plugin) => ({ cli }) => cli.vorpal
.command('bootstrap', 'Bootstraps a Network with test data.')
.option('-n, --network <name>', 'Network to bootstrap')
.option('--wallets <number>', 'Number of wallets to create - default 10')
.option('--rpc <string>', 'Bootstraps a private network with the given rpcURL.')
.option('--testing-only', 'Option to spoof rpc path for testing')
.option('--reset', 'Reset blockchain before bootstrapping')
.action(async (args) => {
const spinner = ora_1.default(`Gathering data for bootstrap`).start();
const walletNames = [];
const numWallets = getNumWallets(args.options);
for (let i = 1; i < numWallets + 1; i += 1) {
walletNames.push(`wallet-${i}`);
}
try {
let bootstrapData;
const cliOptions = {
cli,
args,
options: args.options,
};
if (args.options.rpc != undefined) {
bootstrapData = await getPresetData({
cliOptions,
plugin,
walletNames,
});
}
else {
bootstrapData = await getNEOONEData({
cliOptions,
plugin,
walletNames,
});
}
const { network, master, wallets, assetWallets, tokenWallets } = bootstrapData;
spinner.succeed();
spinner.start(`Bootstrapping network ${bootstrapData.network.name}`);
const keystore = new client_core_1.LocalKeyStore(new client_core_1.LocalMemoryStore());
await addWalletsToKeystore({
keystore,
networkName: network.name,
master,
wallets,
assetWallets,
tokenWallets,
});
const provider = new client_core_1.NEOONEProvider([{ network: network.name, rpcURL: network.rpcURL }]);
const localUserAccountProvider = new client_full_core_1.LocalUserAccountProvider({
keystore,
provider,
});
const providers = {
memory: localUserAccountProvider,
};
const client = new client_full_core_1.Client(providers);
client.hooks.beforeRelay.tapPromise('bootstrap', async (mutableOptions) => {
mutableOptions.systemFee = new bignumber_js_1.default(-1);
});
await client.selectUserAccount(master.accountID);
const developerClient = new client_core_1.DeveloperClient(provider.read(network.name));
spinner.succeed();
await developerClient.updateSettings({
secondsPerBlock: 600,
});
if (args.options.reset) {
spinner.start('Resetting network');
await developerClient.reset();
spinner.succeed();
}
spinner.start('Initializing wallets with funds');
await initializeWallets({
wallets,
master,
client,
developerClient,
});
spinner.succeed();
spinner.start('Setting up asset wallets');
await setupWallets({
wallets: assetWallets,
client,
developerClient,
master,
});
spinner.succeed();
spinner.start('Setting up token wallets');
await setupWallets({
wallets: tokenWallets,
client,
developerClient,
master,
});
spinner.succeed();
spinner.start('Registering test assets');
const assets = await registerAssets({
assetWallets,
client,
developerClient,
});
spinner.succeed();
spinner.start('Issuing assets');
await issueAssets({
assets,
client,
developerClient,
});
spinner.succeed();
spinner.start('Distributing assets');
await transferAssets({
wallets,
assets,
client,
developerClient,
});
spinner.succeed();
spinner.start('Publishing tokens');
const isRPC = args.options.rpc != undefined;
const tokens = await publishTokens({
tokenWallets,
client,
isRPC,
developerClient,
});
spinner.succeed();
spinner.start('Transferring tokens');
await transferTokens({
wallets,
tokens,
developerClient,
});
spinner.succeed();
spinner.start('Claiming GAS');
await initiateClaims({
wallets,
networkName: network.name,
client,
developerClient,
provider,
});
spinner.succeed();
await developerClient.updateSettings({ secondsPerBlock: 15 });
cli.print('Published contracts:');
tokens.forEach(({ name, hash }) => {
cli.print(`${name}:${hash}`);
});
}
catch (error) {
spinner.fail(error);
throw error;
}
});
//# sourceMappingURL=data:application/json;charset=utf8;base64,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