Skip to content

Commit

Permalink
Got transaction signing working.
Browse files Browse the repository at this point in the history
  • Loading branch information
thekevinbrown committed Apr 10, 2019
1 parent fce3c94 commit 874dc27
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 7 deletions.
17 changes: 15 additions & 2 deletions src/accounts/accountManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Api } from 'eosjs';
import { convertLegacyPublicKey } from 'eosjs/dist/eosjs-numeric';
import * as ecc from 'eosjs-ecc';

import { Account } from './account';
Expand All @@ -11,6 +12,12 @@ interface AccountCreationOptions {
}

export class AccountManager {
static createAccount = async (options?: AccountCreationOptions) => {
const [account] = await AccountManager.createAccounts(1, options);

return account;
};

static createAccounts = async (numberOfAccounts = 1, options?: AccountCreationOptions) => {
const accounts = [];
for (let i = 0; i < numberOfAccounts; i++) {
Expand Down Expand Up @@ -39,9 +46,13 @@ export class AccountManager {
if (!account.privateKey) throw new Error('Missing private key.');

if (EOSManager.signatureProvider) {
EOSManager.signatureProvider.keys.set(account.publicKey, account.privateKey);
const nonLegacyPublicKey = convertLegacyPublicKey(account.publicKey);
EOSManager.signatureProvider.keys.set(nonLegacyPublicKey, account.privateKey);
EOSManager.signatureProvider.availableKeys.push(nonLegacyPublicKey);
}

console.log('Signature provider', EOSManager.signatureProvider);

const systemContract = await eos.getContract('eosio');

const actions: any = [
Expand Down Expand Up @@ -78,7 +89,9 @@ export class AccountManager {
},
];

// Do we need to buyrambytes? If there's a system contract with that action we do.
// Note: You can deploy the system without system contracts. In this scenario,
// newaccount alone is enough. If there is a system contract with that action,
// then we definitely need to do it though.
if (systemContract.actions.has('buyrambytes')) {
actions.push({
account: 'eosio',
Expand Down
5 changes: 0 additions & 5 deletions src/cli/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,6 @@ export const runTests = async () => {
mocha.addFile(path.join(workingDirectory, testFile));
}

// Now we're all ready to go. Let's make sure we have enough blocks that our tests will
// work out of the box.
console.log('Waiting for block #4.');
await untilBlockNumber(4);

// Run the tests.
mocha.run(failures => {
process.exitCode = failures ? 1 : 0; // exit with non-zero status if there were failures
Expand Down
1 change: 1 addition & 0 deletions src/contracts/contract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export class Contract {}
106 changes: 106 additions & 0 deletions src/contracts/contractDeployer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import * as path from 'path';
import { readFile as readFileCallback } from 'fs';
import { promisify } from 'util';
import { Serialize } from 'eosjs';

const readFile = promisify(readFileCallback);

import { Contract } from './contract';
import { Account, AccountManager } from '../accounts';
import { EOSManager } from '../eosManager';

export class ContractDeployer {
public static async deployAtName<T extends Contract>(
account: Account,
contractIdentifier: string
) {
console.log('Available keys', await EOSManager.signatureProvider.getAvailableKeys());

const buffer = new Serialize.SerialBuffer({
textEncoder: EOSManager.api.textEncoder,
textDecoder: EOSManager.api.textDecoder,
});

const abiPath = path.join('.lamington', 'compiled_contracts', `${contractIdentifier}.abi`);
const wasmPath = path.join('.lamington', 'compiled_contracts', `${contractIdentifier}.wasm`);

let abi = JSON.parse(await readFile(abiPath, 'utf8'));
const wasm = await readFile(wasmPath);

const abiDefinition = EOSManager.api.abiTypes.get(`abi_def`);

// We need to make sure the abi has every field in abiDefinition.fields
// otherwise serialize throws
if (!abiDefinition)
throw new Error('Could not retrieve abiDefinition from EOS API when flattening ABIs.');

abi = abiDefinition.fields.reduce(
(acc, { name: fieldName }) => Object.assign(acc, { [fieldName]: acc[fieldName] || [] }),
abi
);
abiDefinition.serialize(buffer, abi);

const requiredKeys = await EOSManager.rpc.getRequiredKeys({
transaction: {
actions: [
{
account: `eosio`,
name: `setcode`,
authorization: account.active,
data: {
account: account.name,
vmtype: 0,
vmversion: 0,
code: wasm.toString(`hex`),
},
},
{
account: `eosio`,
name: `setabi`,
authorization: account.active,
data: {
account: account.name,
abi: Buffer.from(buffer.asUint8Array()).toString(`hex`),
},
},
],
},
availableKeys: await EOSManager.signatureProvider.getAvailableKeys(),
});

console.log('Required keys', requiredKeys);

await EOSManager.transact({
actions: [
{
account: `eosio`,
name: `setcode`,
authorization: account.active,
data: {
account: account.name,
vmtype: 0,
vmversion: 0,
code: wasm.toString(`hex`),
},
},
{
account: `eosio`,
name: `setabi`,
authorization: account.active,
data: {
account: account.name,
abi: Buffer.from(buffer.asUint8Array()).toString(`hex`),
},
},
],
});

return new Contract();
}

public static async deployClean<T extends Contract>(contractIdentifier: string) {
const account = await AccountManager.createAccount();

return await ContractDeployer.deployAtName<T>(account, contractIdentifier);
}
}
2 changes: 2 additions & 0 deletions src/contracts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './contract';
export * from './contractDeployer';
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './accounts';
export * from './contracts';

import * as cliUtils from './cli/utils';
export const CLI = cliUtils;
2 changes: 2 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ export const untilBlockNumber = async (number: number) => {

export const sleep = async (delayInMs: number) =>
new Promise(resolve => setTimeout(resolve, delayInMs));

export const nextBlock = () => sleep(500);

0 comments on commit 874dc27

Please sign in to comment.