Add storage subscription API endpoints (#126)
* Add storage subscriptions * StorageResult formatting * Decoding WIP * Storage subsciptions in place * Allow null decodes, ref https://github.com/polkadot-js/apps/issues/215 * e2e tests for subscribeStorage * Cache subscription results, return with changeset
This commit is contained in:
@@ -84,6 +84,6 @@ export default function mocks ({ emitter, storage, subscriptions }: MockState):
|
||||
|
||||
setStorageBn(storage, stateTimestamp.current, Math.floor(Date.now() / 1000));
|
||||
|
||||
updateSubs(subscriptions, 'subscribe_newHead', headerEncode(newHead));
|
||||
updateSubs(subscriptions, 'chain_subscribeNewHead', headerEncode(newHead));
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('state', () => {
|
||||
expect(
|
||||
state.subscriptions
|
||||
).toMatchObject({
|
||||
'subscribe_newHead': {
|
||||
'chain_subscribeNewHead': {
|
||||
callbacks: {},
|
||||
lastValue: null
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ const SUBSCRIPTIONS: string[] = Array.prototype.concat.apply(
|
||||
.filter((method) =>
|
||||
method.isSubscription
|
||||
)
|
||||
.map(({ name }) =>
|
||||
`subscribe_${name}`
|
||||
.map(({ name, section }) =>
|
||||
`${section}_${name}`
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -19,7 +19,7 @@ describe('subscribe', () => {
|
||||
});
|
||||
|
||||
it('returns a subscription id', () => {
|
||||
return subscribe(state, 'subscribe_newHead', [() => void 0]).then((id) => {
|
||||
return subscribe(state, 'chain_subscribeNewHead', [() => void 0]).then((id) => {
|
||||
expect(id).toEqual(state.subscriptionId);
|
||||
});
|
||||
});
|
||||
@@ -27,16 +27,16 @@ describe('subscribe', () => {
|
||||
it('stores the mapping values', () => {
|
||||
const cb = () => void 0;
|
||||
|
||||
return subscribe(state, 'subscribe_newHead', [cb]).then((id) => {
|
||||
expect(state.subscriptionMap[id]).toEqual('subscribe_newHead');
|
||||
expect(state.subscriptions['subscribe_newHead'].callbacks[id]).toEqual(cb);
|
||||
return subscribe(state, 'chain_subscribeNewHead', [cb]).then((id) => {
|
||||
expect(state.subscriptionMap[id]).toEqual('chain_subscribeNewHead');
|
||||
expect(state.subscriptions['chain_subscribeNewHead'].callbacks[id]).toEqual(cb);
|
||||
});
|
||||
});
|
||||
|
||||
it('calls back with the last known value', (done) => {
|
||||
state.subscriptions['subscribe_newHead'].lastValue = 'testValue';
|
||||
state.subscriptions['chain_subscribeNewHead'].lastValue = 'testValue';
|
||||
|
||||
subscribe(state, 'subscribe_newHead', [(_, value) => {
|
||||
subscribe(state, 'chain_subscribeNewHead', [(_, value) => {
|
||||
expect(value).toEqual('testValue');
|
||||
done();
|
||||
}]);
|
||||
|
||||
@@ -13,23 +13,23 @@ describe('unsubscribe', () => {
|
||||
beforeEach(() => {
|
||||
state = createState();
|
||||
|
||||
return subscribe(state, 'subscribe_newHead', [() => void 0]).then((_id) => {
|
||||
return subscribe(state, 'chain_subscribeNewHead', [() => void 0]).then((_id) => {
|
||||
id = _id;
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on unknown ids', () => {
|
||||
return unsubscribe(state, 'subscribe_newHead', 5).catch((error) => {
|
||||
return unsubscribe(state, 'chain_subscribeNewHead', 5).catch((error) => {
|
||||
expect(error.message).toMatch(/Unable to find/);
|
||||
});
|
||||
});
|
||||
|
||||
it('unsubscribes successfully', () => {
|
||||
return unsubscribe(state, 'subscribe_newHead', id);
|
||||
return unsubscribe(state, 'chain_subscribeNewHead', id);
|
||||
});
|
||||
|
||||
it('fails on double unsubscribe', () => {
|
||||
return unsubscribe(state, 'subscribe_newHead', id)
|
||||
return unsubscribe(state, 'chain_subscribeNewHead', id)
|
||||
.then(() => unsubscribe(state, id))
|
||||
.catch((error) => {
|
||||
expect(error.message).toMatch(/Unable to find/);
|
||||
@@ -37,9 +37,9 @@ describe('unsubscribe', () => {
|
||||
});
|
||||
|
||||
it('clears the subscriptions', () => {
|
||||
return unsubscribe(state, 'subscribe_newHead', id).then(() => {
|
||||
return unsubscribe(state, 'chain_subscribeNewHead', id).then(() => {
|
||||
expect(state.subscriptionMap[id]).not.toBeDefined();
|
||||
expect(state.subscriptions['subscribe_newHead'].callbacks[id]).not.toBeDefined();
|
||||
expect(state.subscriptions['chain_subscribeNewHead'].callbacks[id]).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2017-2018 @polkadot/api-provider authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import storage from '@polkadot/storage';
|
||||
|
||||
import createApi from '../../api/src';
|
||||
import Ws from '../src/ws';
|
||||
|
||||
describe.skip('e2e', () => {
|
||||
let api;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.setTimeout(30000);
|
||||
api = createApi(new Ws('ws://127.0.0.1:9944'));
|
||||
});
|
||||
|
||||
it('subscribes to chain_subscribeNewHead', (done) => {
|
||||
let count = 0;
|
||||
|
||||
// tslint:disable-next-line
|
||||
api.chain
|
||||
.subscribeNewHead((error, data) => {
|
||||
if (error) {
|
||||
return done(error);
|
||||
}
|
||||
|
||||
expect(data).toBeDefined();
|
||||
|
||||
if (++count === 3) {
|
||||
done();
|
||||
}
|
||||
})
|
||||
.then((subscriptionId) => {
|
||||
console.log('newHead: subscriptionId =', subscriptionId);
|
||||
});
|
||||
});
|
||||
|
||||
it('subscribes to storage', (done) => {
|
||||
api.state
|
||||
.subscribeStorage([
|
||||
[storage.staking.public.freeBalanceOf, '5Ejbye9R8ygByQPrDSasaUid1munedPZUmg4f118HGmtodGp'],
|
||||
[storage.staking.public.freeBalanceOf, '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFacT7']
|
||||
], (error, data) => {
|
||||
if (error) {
|
||||
return done(error);
|
||||
}
|
||||
|
||||
expect(data).toHaveLength(2);
|
||||
expect(data[0].toNumber()).toEqual(0);
|
||||
expect(data[1].toNumber()).not.toEqual(0);
|
||||
|
||||
done();
|
||||
})
|
||||
.then((subscriptionId) => {
|
||||
console.log('newHead: subscriptionId =', subscriptionId);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,36 +0,0 @@
|
||||
// Copyright 2017-2018 @polkadot/api-provider authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterface } from '../../api/src/types';
|
||||
|
||||
import createApi from '../../api/src';
|
||||
import Ws from '../src/ws';
|
||||
|
||||
describe.skip('e2e', () => {
|
||||
let api: ApiInterface;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.setTimeout(30000);
|
||||
api = createApi(new Ws('ws://127.0.0.1:9944'));
|
||||
});
|
||||
|
||||
it('subscribes to client_newHead', (done) => {
|
||||
let count = 0;
|
||||
|
||||
// tslint:disable-next-line
|
||||
api.chain
|
||||
.newHead((error: Error | null, data: any) => {
|
||||
console.log('newHead: result =', [error, data]);
|
||||
|
||||
expect(data).toBeDefined();
|
||||
|
||||
if (++count === 3) {
|
||||
done();
|
||||
}
|
||||
})
|
||||
.then((subscriptionId) => {
|
||||
console.log('newHead: subscriptionId =', subscriptionId);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user