Skip to content

Commit

Permalink
Documented API methods
Browse files Browse the repository at this point in the history
All API methods have now be documented or updated
  • Loading branch information
MitchPierias committed Apr 25, 2019
1 parent 3b5b914 commit ee529c7
Show file tree
Hide file tree
Showing 13 changed files with 270 additions and 94 deletions.
25 changes: 23 additions & 2 deletions src/accounts/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@ import { AccountManager } from './accountManager';

export class Account {

/** EOSIO account name */
public name: string;
/** EOSIO account public key */
public publicKey: string;
/** EOSIO account private key */
public privateKey: string;
/** EOSIO account permissions */
public permissions: Permissions;

constructor(name: string, privateKey: string, publicKey?: string) {
// Store references
this.name = name;
this.privateKey = privateKey;
this.publicKey = publicKey || ecc.privateToPublic(privateKey);

// Set default permissions
this.permissions = {
active: {
actor: name,
Expand All @@ -27,6 +32,11 @@ export class Account {
};
}

/**
* Returns a configured active key permission
* @author Kevin Brown <github.com/thekevinbrown>
* @returns Valid active key
*/
public get active() {
return [
{
Expand All @@ -36,6 +46,11 @@ export class Account {
];
}

/**
* Returns a configured owner key permission
* @author Kevin Brown <github.com/thekevinbrown>
* @returns Valid owner key
*/
public get owner() {
return [
{
Expand All @@ -45,7 +60,13 @@ export class Account {
];
}

public addCodePermission = async (contract: Contract) => {
/**
* Adds the `eosio.code` permission to this account
* @author Kevin Brown <github.com/thekevinbrown>
* @author Mitch Pierias <github.com/MitchPierias>
* @returns Add permission transaction promise
*/
public addCodePermission = async () => {
await AccountManager.addCodePermission(this);
};
}
72 changes: 45 additions & 27 deletions src/accounts/accountManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,70 @@ import * as ecc from 'eosjs-ecc';
import { Account } from './account';
import { accountNameFromPublicKey } from './utils';
import { EOSManager } from '../eosManager';
import { Contract } from '../contracts';

interface AccountCreationOptions {
creator?: Account;
eos?: Api;
}

export class AccountManager {

/**
* Generates a new random account
* @note Shorthand method for [[AccountManager.createAccounts]]
* @author Kevin Brown <github.com/thekevinbrown>
* @param options Optional account creation settings
* @returns Result returned from [[AccountManager.createAccounts]]
*/
static createAccount = async (options?: AccountCreationOptions) => {
const [account] = await AccountManager.createAccounts(1, options);

return account;
};

/**
* Generates a specified number of random accounts
* @author Kevin Brown <github.com/thekevinbrown>
* @param numberOfAccounts Number of accounts to generate
* @returns Array of created account transaction promises
*/
static createAccounts = async (numberOfAccounts = 1, options?: AccountCreationOptions) => {
const accounts = [];

// Repeat account creation for specified
for (let i = 0; i < numberOfAccounts; i++) {
const privateKey = await ecc.unsafeRandomKey();
const publicKey = await ecc.privateToPublic(privateKey);
const accountName = accountNameFromPublicKey(publicKey);
const account = new Account(accountName, privateKey);

// Publish the new account and store result
await AccountManager.setupAccount(account, options);

accounts.push(account);
}

// Return created acounts
return accounts;
};

/**
* Publishes a new account and allocates ram where possible
* @author Kevin Brown <github.com/thekevinbrown>
* @param account [[Account]] to publish
* @param options Optional account settings
* @returns Transaction result promise
*/
static setupAccount = async (account: Account, options?: AccountCreationOptions) => {
const { creator, eos } = AccountManager.flattenOptions(options);

// Validate account contains required values
if (!account.name) throw new Error('Missing account name.');
if (!account.publicKey) throw new Error('Missing public key.');
if (!account.privateKey) throw new Error('Missing private key.');

// Configure the Signature Provider if available
if (EOSManager.signatureProvider) {
const nonLegacyPublicKey = convertLegacyPublicKey(account.publicKey);
EOSManager.signatureProvider.keys.set(nonLegacyPublicKey, account.privateKey);
EOSManager.signatureProvider.availableKeys.push(nonLegacyPublicKey);
}

// Get the system contract
const systemContract = await eos.getContract('eosio');

// Build account creation actions
const actions: any = [
{
account: 'eosio',
Expand Down Expand Up @@ -100,7 +118,6 @@ export class AccountManager {
},
});
}

// Same deal for delegatebw. Only if it's actually a thing.
if (systemContract.actions.has('delegatebw')) {
actions.push({
Expand All @@ -116,44 +133,42 @@ export class AccountManager {
},
});
}

// Execute the transaction
return await EOSManager.transact({ actions }, eos);
};

/**
* Grants `eosio.code` permission to the specified account's `active` key
* @note Should be moved to the `contracts/contract.ts` I think?
* @note Actually it is `account` based and not specific to contracts...
* @author Kevin Brown
* @author Mitch Pierias
* @author Kevin Brown <github.com/thekevinbrown>
* @author Mitch Pierias <github.com/MitchPierias>
* @param account Account without `eosio.code` permissions
*/
static addCodePermission = async (account: Account) => {
// We need to get their existing permissions, then add in a new eosio.code permission for this contract.
const { permissions } = await EOSManager.rpc.get_account(account.name);
const active = permissions.find((permission: any) => permission.perm_name == 'active');

const auth = active.required_auth;
const existingPermission = auth.accounts.find(
const { required_auth } = permissions.find((permission: any) => permission.perm_name == 'active');
// Check if `eosio.code` has already been set
const existingPermission = required_auth.accounts.find(
(account: any) =>
account.permission.actor === account.name &&
account.permission.permission === 'eosio.code'
);

// Throw if permission exists
if (existingPermission) {
throw new Error(
`Code permission is already present on account ${account.name} for contract ${
account.name
}`
);
}

// Add it in.
auth.accounts.push({
// Append the `eosio.code` permission to existing
required_auth.accounts.push({
permission: { actor: account.name, permission: 'eosio.code' },
weight: 1,
});

// Construct the update actions
const actions: any = [
{
account: 'eosio',
Expand All @@ -163,16 +178,19 @@ export class AccountManager {
account: account.name,
permission: 'active',
parent: 'owner',
auth,
required_auth,
},
},
];

//console.log(JSON.stringify(actions, null, '\t'))

// Execute the transaction actions
await EOSManager.transact({ actions });
};

/**
* Flattens account creation options
* @author Kevin Brown <github.com/thekevinbrown>
* @returns Account creation options
*/
private static flattenOptions(options?: AccountCreationOptions) {
const creator = (options && options.creator) || EOSManager.adminAccount;
const eos = (options && options.eos) || EOSManager.api;
Expand Down
17 changes: 15 additions & 2 deletions src/accounts/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as ecc from 'eosjs-ecc';

export const accountNameFromPublicKey = (publicKey: string) => hashToEOSName(ecc.sha256(publicKey));
/** Digit pattern expression */
const digitPattern = /[06789]/g;

/** Digit mapping lookup */
const digitMapping: { [key: string]: string } = {
'0': '1',
'6': '2',
Expand All @@ -10,8 +12,19 @@ const digitMapping: { [key: string]: string } = {
'9': '5',
};

const digitPattern = /[06789]/g;
/**
* Generates an account name from the specified public key
* @author Kevin Brown <github.com/thekevinbrown>
* @param publicKey Valid EOSIO public key
* @returns EOSIO account name
*/
export const accountNameFromPublicKey = (publicKey: string) => hashToEOSName(ecc.sha256(publicKey));

/**
* Generates an account name from a hashed public key
* @author Kevin Brown <github.com/thekevinbrown>
* @returns EOSIO account name
*/
export const hashToEOSName = (data: string) =>
`l${data
.substring(0, 11)
Expand Down
6 changes: 6 additions & 0 deletions src/cli/lamington-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import { eosIsReady, startEos, stopContainer, buildAll } from './utils';
import { GitIgnoreManager } from '../gitignoreManager';
import { ConfigManager } from '../configManager';

/**
* Executes a contract build procedure
* @note Keep alive setup is incomplete
* @author Kevin Brown <github.com/thekevinbrown>
* @author Mitch Pierias <github.com/MitchPierias>
*/
const run = async () => {
// Initialize configuration
await ConfigManager.initWithDefaults();
Expand Down
5 changes: 5 additions & 0 deletions src/cli/lamington-start.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { startEos } from './utils';

/**
* Starts EOS and throws caught errors
* @note This should handle caught errors
* @author Kevin Brown <github.com/thekevinbrown>
*/
startEos().catch(error => {
throw error;
});
4 changes: 4 additions & 0 deletions src/cli/lamington-stop.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { stopContainer } from './utils';

/**
* Stops the current Lamington docker container
* @author Kevin Brown <github.com/thekevinbrown>
*/
stopContainer()
.then(() => console.log('Lamington container stopped.'))
.catch(error => {
Expand Down
6 changes: 6 additions & 0 deletions src/cli/lamington-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import { eosIsReady, startEos, runTests, stopContainer, buildAll } from './utils
import { GitIgnoreManager } from '../gitignoreManager';
import { ConfigManager } from '../configManager';

/**
* Executes a build and test procedure
* @note Keep alive setup is incomplete
* @author Kevin Brown <github.com/thekevinbrown>
* @author Mitch Pierias <github.com/MitchPierias>
*/
const run = async () => {
// Initialize the configuration
await ConfigManager.initWithDefaults();
Expand Down
Loading

0 comments on commit ee529c7

Please sign in to comment.