Skip to content

Commit

Permalink
Merge pull request #28 from PolymathNetwork/feat/MSDK-78-private-polk…
Browse files Browse the repository at this point in the history
…adot-api

feat: prevent the tx submodule from being accessed without an acc
  • Loading branch information
monitz87 authored Feb 28, 2020
2 parents f0c33e9 + e1a672c commit af31a5a
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 14 deletions.
14 changes: 7 additions & 7 deletions src/__tests__/Polymesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import { PolkadotMockFactory } from '~/testUtils/mocks';
describe('Polymesh Class', () => {
const polkadotMockFactory = new PolkadotMockFactory();
polkadotMockFactory.initMocks({ mockContext: true });
let mockWsProvider: MockManager<polkadotModule.Keyring>;
let mockWsProvider: MockManager<polkadotModule.WsProvider>;

beforeEach(() => {
mockWsProvider = ImportMock.mockClass(polkadotModule, 'WsProvider');
mockWsProvider = ImportMock.mockClass<polkadotModule.WsProvider>(polkadotModule, 'WsProvider');
});

afterEach(() => {
Expand All @@ -36,26 +36,26 @@ describe('Polymesh Class', () => {
sinon.assert.match(polymesh instanceof Polymesh, true);
});

test('should throw if ApiPromise fails in the connection process', async () => {
test('should throw if ApiPromise fails in the connection process', () => {
polkadotMockFactory.throwOnApiCreation();
const nodeUrl = 'wss://some.url';
const polymeshApiPromise = Polymesh.connect({
nodeUrl,
});

await expect(polymeshApiPromise).rejects.toThrow(
return expect(polymeshApiPromise).rejects.toThrow(
`Error while connecting to "${nodeUrl}": "Error"`
);
});

test('should throw if Context create method fails', async () => {
test('should throw if Context create method fails', () => {
polkadotMockFactory.throwOnContextCreation();
const nodeUrl = 'wss://some.url';
const polymeshApiPromise = Polymesh.connect({
nodeUrl,
});

await expect(polymeshApiPromise).rejects.toThrow(
return expect(polymeshApiPromise).rejects.toThrow(
`Error while connecting to "${nodeUrl}": "Error"`
);
});
Expand All @@ -69,7 +69,7 @@ describe('Polymesh Class', () => {
nodeUrl: 'wss://some.url',
});

await expect(polymesh.getIdentityBalance()).rejects.toThrow(
return expect(polymesh.getIdentityBalance()).rejects.toThrow(
'The current account does not have an associated identity'
);
});
Expand Down
22 changes: 16 additions & 6 deletions src/context/__tests__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Context class', () => {
polkadotMockFactory.initMocks();

beforeEach(() => {
mockKeyring = ImportMock.mockClass(polkadotModule, 'Keyring');
mockKeyring = ImportMock.mockClass<polkadotModule.Keyring>(polkadotModule, 'Keyring');
});

afterEach(() => {
Expand All @@ -27,14 +27,24 @@ describe('Context class', () => {
polkadotMockFactory.cleanup();
});

test('should throw an error if accessing the transaction submodule without an active account', async () => {
const context = await Context.create({
polymeshApi: polkadotMockFactory.getApiInstance(),
});

expect(() => context.polymeshApi.tx).toThrow(
'Cannot perform transactions without an active account'
);
});

describe('method: create', () => {
test('should throw if accountSeed parameter is not a 32 length string', async () => {
test('should throw if accountSeed parameter is not a 32 length string', () => {
const context = Context.create({
polymeshApi: polkadotMockFactory.getApiInstance(),
accountSeed: 'abc',
});

await expect(context).rejects.toThrow(new Error('Seed must be 32 characters in length'));
return expect(context).rejects.toThrow(new Error('Seed must be 32 characters in length'));
});

test('should create a Context class with Pair and Identity attached', async () => {
Expand Down Expand Up @@ -74,16 +84,16 @@ describe('Context class', () => {
expect(context.currentIdentity).toBe(undefined);
});

test('should throw if the account seed is not assotiated with an IdentityId ', async () => {
test('should throw if the account seed is not assotiated with an IdentityId ', () => {
mockKeyring.mock('addFromSeed', 'currentPair');
polkadotMockFactory.createQueryStub('identity', 'keyToIdentityIds');

const context = Context.create({
const contextPromise = Context.create({
polymeshApi: polkadotMockFactory.getApiInstance(),
accountSeed: 'Alice'.padEnd(32, ' '),
});

await expect(context).rejects.toThrow(new Error('Identity ID does not exist'));
return expect(contextPromise).rejects.toThrow(new Error('Identity ID does not exist'));
});
});

Expand Down
14 changes: 13 additions & 1 deletion src/context/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,18 @@ export class Context {
private constructor(params: ConstructorParams) {
const { polymeshApi, keyring, pair } = params;

this.polymeshApi = polymeshApi;
this.polymeshApi = new Proxy(polymeshApi, {
get: (target, prop: keyof ApiPromise): ApiPromise[keyof ApiPromise] => {
if (prop === 'tx' && !this.currentPair) {
throw new PolymeshError({
code: ErrorCode.FatalError,
message: 'Cannot perform transactions without an active account',
});
}

return target[prop];
},
});
this.keyring = keyring;

if (pair) {
Expand Down Expand Up @@ -140,6 +151,7 @@ export class Context {
}

const balance = await this.polymeshApi.query.balances.freeBalance(address);

return balanceToBigNumber(balance);
};
}

0 comments on commit af31a5a

Please sign in to comment.