renaming phoenix to subspace pt1.

This commit is contained in:
Richard Ramos 2019-09-27 16:04:01 -04:00
parent f99a31ffcf
commit 4c258a8da6
17 changed files with 97 additions and 103 deletions

View File

@ -30,8 +30,8 @@ const Phoenix = require('phoenix');
To interact with the EVM, Phoenix requires a valid websockets Web3 provider.
```js
const eventSyncer = new Phoenix(web3.currentProvider);
await eventSyncer.init();
const subspace = new Phoenix(web3.currentProvider);
await subspace.init();
```
In addition to the provider, `Phoenix` also accepts an `options` object with settings that can change its behavior:
@ -47,7 +47,7 @@ const contractObject = ...; // A web3.eth.Contract object initialized with an ad
const functionName = "..."; // string containing the name of the contract's constant/view function to track.
const functionArgs = []; // array containing the arguments of the function to track. Optional
const callOptions = {from: web3.eth.defaultAccount}; // Options used for calling. Only `from`, `gas` and `gasPrice` are accepted. Optional
eventSyncer.trackProperty(contractObject, functionName, functionArgs, callOptions)
subspace.trackProperty(contractObject, functionName, functionArgs, callOptions)
.subscribe(value => console.dir)
```
This can be used as well to track public state variables, since they implicity create a view function when they're declared public. The `functionName` would be the same as the variable name, and `functionArgs` would have a value when the type is a `mapping` or `array` (since these require an index value to query them).
@ -61,8 +61,8 @@ const contractObject = ...; // A web3.eth.Contract object initialized with an ad
const eventName = "..."; // string containing the name of the event to track.
const options = { filter: { }, fromBlock: 1 }; // options used to query the events. Optional
eventSyncer.trackEvent(contractObject, eventName, options)
.subscribe(eventData => console.dir);
subspace.trackEvent(contractObject, eventName, options)
.subscribe(eventData => console.dir);
```
@ -74,7 +74,7 @@ Reacts to changes in the ETH or ERC20 balance of addresses for each mined block
// Tracking ETH balance
const address = "0x0001020304050607080900010203040506070809";
eventSyncer
subspace
.trackBalance(address)
.subscribe((balance) => {
console.log("ETH balance is ", balance)
@ -86,10 +86,10 @@ eventSyncer
const address = "0x0001020304050607080900010203040506070809";
const tokenAddress = "0x744d70fdbe2ba4cf95131626614a1763df805b9e"; // SNT Address
eventSyncer.trackBalance(address, tokenAddress)
.subscribe((balance) => {
console.log("Token balance is ", balance)
});
subspace.trackBalance(address, tokenAddress)
.subscribe((balance) => {
console.log("Token balance is ", balance)
});
```
@ -100,7 +100,7 @@ Subscriptions are triggered each time an observable emits a new value. These sub
Subscriptions can be disposed by executing the method `unsubscribe()` liberating the resource held by it:
```js
const subscription = eventSyncer.trackBalance(address, tokenAddress).subscribe(value => { /* Do something */ });
const subscription = subspace.trackBalance(address, tokenAddress).subscribe(value => { /* Do something */ });
// ...
@ -108,10 +108,10 @@ subscription.unsubscribe();
```
#### Cleanup
If Phoenix `eventSyncer` is not needed anymore, you need to invoke `clean()` to dispose and perform the cleanup necessary to remove the internal subscriptions and interval timers created by Phoenix during its normal execution. Any subscription created via the tracking methods must be unsubscribed manually (in the current version).
If Phoenix `subspace` is not needed anymore, you need to invoke `clean()` to dispose and perform the cleanup necessary to remove the internal subscriptions and interval timers created by Phoenix during its normal execution. Any subscription created via the tracking methods must be unsubscribed manually (in the current version).
```
eventSyncer.clean();
subspace.clean();
```
## Contribution

View File

@ -38,15 +38,15 @@ class App extends React.Component {
};
async componentDidMount() {
const eventSyncer = new Subspace(web3.currentProvider);
await eventSyncer.init();
const subspace = new Subspace(web3.currentProvider);
await subspace.init();
MyContractInstance = await MyContract.getInstance();
const resolvers = {
Query: {
myEvents: () => {
return eventSyncer.trackEvent(MyContractInstance, 'MyEvent', {filter: {}, fromBlock: 1})
return subspace.trackEvent(MyContractInstance, 'MyEvent', {filter: {}, fromBlock: 1})
}
}
};

View File

@ -13,9 +13,9 @@ class App extends React.Component {
async componentDidMount() {
MyContractInstance = await MyContract.getInstance();
const eventSyncer = new Subspace(web3.currentProvider);
await eventSyncer.init();
eventSubscription = eventSyncer.trackEvent(MyContractInstance, "MyEvent", { filter: {}, fromBlock: 1 })
const subspace = new Subspace(web3.currentProvider);
await subspace.init();
eventSubscription = subspace.trackEvent(MyContractInstance, "MyEvent", { filter: {}, fromBlock: 1 })
.subscribe(this.props.myAction);
}

View File

@ -15,13 +15,13 @@ class App extends React.Component {
async componentDidMount() {
MyContractInstance = await MyContract.getInstance(); //
const eventSyncer = new Subspace(web3.currentProvider);
await eventSyncer.init();
const subspace = new Subspace(web3.currentProvider);
await subspace.init();
const myEventObservable$ = eventSyncer.trackEvent(MyContractInstance, "MyEvent", {filter: {}, fromBlock: 1 });
const myEventObservable$ = subspace.trackEvent(MyContractInstance, "MyEvent", {filter: {}, fromBlock: 1 });
// If you want to return all the events in an array, you can pipe the scan operator to the observable
// const myEventObservable$ = eventSyncer.trackEvent(MyContractInstance, "MyEvent", {filter: {}, fromBlock: 1 })
// const myEventObservable$ = subspace.trackEvent(MyContractInstance, "MyEvent", {filter: {}, fromBlock: 1 })
// .pipe(scan((accum, val) => [...accum, val], []));
// Your observable component would receive the eventData as an array instead of an object

View File

@ -7,8 +7,8 @@ const gql = require("graphql-tag");
const { graphql } = require("reactive-graphql");
const run = (async () => {
const eventSyncer = new Subspace(web3.currentProvider);
await eventSyncer.init();
const subspace = new Subspace(web3.currentProvider);
await subspace.init();
const MyContractInstance = await MyContract.getInstance();
@ -31,7 +31,7 @@ const run = (async () => {
const resolvers = {
Query: {
myEvents: () => {
return eventSyncer.trackEvent(MyContractInstance, 'MyEvent', {filter: {}, fromBlock: 1})
return subspace.trackEvent(MyContractInstance, 'MyEvent', {filter: {}, fromBlock: 1})
}
}
};

View File

@ -21,7 +21,7 @@ import web3 from "./web3";
import Subspace from "phoenix";
let MyContractInstance;
let eventSyncer;
let subspace;
const deployContractEpic = action$ =>
action$.pipe(
@ -39,8 +39,8 @@ const initSubspaceEpic = action$ =>
action$.pipe(
ofType(INIT_SUBSPACE),
mergeMap(() => {
eventSyncer = new Subspace(web3.currentProvider);
return eventSyncer.init();
subspace = new Subspace(web3.currentProvider);
return subspace.init();
}),
mapTo(subspaceReady())
);
@ -50,7 +50,7 @@ const trackEventEpic = action$ =>
ofType(SUBSPACE_READY),
mergeMap(() => {
createDummyTransaction();
return eventSyncer
return subspace
.trackEvent(MyContractInstance, "MyEvent", { filter: {}, fromBlock: 1 })
.pipe(
map(eventData => {

View File

@ -13,13 +13,13 @@ store.subscribe(() => console.log("=====\n", store.getState()))
const run = async () => {
const MyContractInstance = await MyContract.getInstance(); //
const eventSyncer = new Subspace(web3.currentProvider);
await eventSyncer.init();
const subspace = new Subspace(web3.currentProvider);
await subspace.init();
eventSyncer.trackEvent(MyContractInstance, "MyEvent", {filter: {}, fromBlock: 1 })
.subscribe(eventData => {
store.dispatch(myAction(eventData));
});
subspace.trackEvent(MyContractInstance, "MyEvent", {filter: {}, fromBlock: 1 })
.subscribe(eventData => {
store.dispatch(myAction(eventData));
});
// Dispatch some actions
MyContractInstance.methods.myFunction().send({from: web3.eth.defaultAccount});

View File

@ -1,6 +1,6 @@
{
"name": "phoenix",
"version": "1.0.0",
"name": "@status-im/subspace",
"version": "0.0.1",
"description": "",
"main": "./dist/node.js",
"browser": "./dist/browser.js",

View File

@ -1,6 +1,7 @@
const { makeExecutableSchema } = require("graphql-tools");
const gql = require( "graphql-tag");
const graphql = require( "reactive-graphql").graphql;
const Subspace = require('../dist/node.js');
const Web3Eth = require('web3-eth');
@ -18,10 +19,9 @@ async function run() {
await EscrowContract.methods.createEscrow(1, accounts[1], accounts[0]).send({from: accounts[0]})
await EscrowContract.methods.createEscrow(1, accounts[0], accounts[2]).send({from: accounts[0]})
const EventSyncer = require('../src/eventSyncer.js')
const eventSyncer = new EventSyncer(eth.currentProvider);
const subspace = new Subspace(eth.currentProvider);
await eventSyncer.init()
await subspace.init()
setInterval(async () => {
await EscrowContract.methods.createEscrow(1, accounts[0], accounts[1]).send({from: accounts[0]})
@ -41,7 +41,7 @@ async function run() {
const resolvers = {
Query: {
escrows: () => {
return eventSyncer.trackEvent(EscrowContract, 'Created', { filter: { buyer: accounts[0] }, fromBlock: 1 })
return subspace.trackEvent(EscrowContract, 'Created', { filter: { buyer: accounts[0] }, fromBlock: 1 })
}
}
};

View File

@ -1,7 +1,7 @@
const { makeExecutableSchema } = require("graphql-tools");
const gql = require( "graphql-tag");
const graphql = require( "reactive-graphql").graphql;
const Subspace = require('../dist/node.js');
const { map, scan, last, distinctUntilChanged, pluck } = require('rxjs/operators');
const Web3Eth = require('web3-eth');
const {$average} = require('../src/operators');
@ -20,10 +20,9 @@ async function run() {
await RatingContract.methods.doRating(1, 1).send({from: accounts[0]})
await RatingContract.methods.doRating(1, 5).send({from: accounts[0]})
const EventSyncer = require('../src/eventSyncer.js')
const eventSyncer = new EventSyncer(eth.currentProvider);
const subspace = new Subspace(eth.currentProvider);
await eventSyncer.init()
await subspace.init()
const typeDefs = `
type Escrow {
@ -38,12 +37,12 @@ async function run() {
const resolvers = {
Escrow: {
averageRating: (something, params) => {
return eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe( $average(x => parseInt(x.rating)))
return subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe( $average(x => parseInt(x.rating)))
}
},
Query: {
escrows: () => {
// return eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), $average())
// return subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), $average())
},
escrow: (something, params) => {
console.dir(something) // error object?
@ -72,12 +71,12 @@ async function run() {
// TODO: would be nice if trackEvent was smart enough to understand the type of returnValues and do the needed conversions
// eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
// subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
// eventSyncer.trackEvent(RatingContract, 'Rating').pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
// eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => x.rating)).subscribe((v) => {
// subspace.trackEvent(RatingContract, 'Rating').pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
// subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => x.rating)).subscribe((v) => {
// eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
// subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
// console.dir("value is ")
// console.dir(v)
// });
@ -87,10 +86,10 @@ async function run() {
// return acc;
// }, [])
// // eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), max, distinctUntilChanged()).subscribe((v) => {
// // eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), last()).subscribe((v) => {
// // subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), max, distinctUntilChanged()).subscribe((v) => {
// // subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), last()).subscribe((v) => {
// eventSyncer.trackEvent(RatingContract, 'Rating').pipe(map(x => parseInt(x.rating)), max, distinctUntilChanged()).subscribe((v) => {
// subspace.trackEvent(RatingContract, 'Rating').pipe(map(x => parseInt(x.rating)), max, distinctUntilChanged()).subscribe((v) => {
// console.dir("max known rating is")
// console.dir(v)
// });

View File

@ -1,6 +1,7 @@
const { map, scan, last, distinctUntilChanged } = require('rxjs/operators');
const Web3Eth = require('web3-eth');
const {deployRatingContract} = require('./utils-web3');
const Subspace = require('../dist/node.js');
let eth = new Web3Eth("ws://localhost:8545");
@ -26,18 +27,17 @@ async function run() {
// console.dir(event)
})
const EventSyncer = require('../dist/node.js');
const eventSyncer = new EventSyncer(eth.currentProvider);
const subspace = new Subspace(eth.currentProvider);
await eventSyncer.init()
await subspace.init()
// TODO: would be nice if trackEvent was smart enough to understand the type of returnValues and do the needed conversions
// eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
// subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
// eventSyncer.trackEvent(RatingContract, 'Rating').pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
// eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => x.rating)).subscribe((v) => {
// subspace.trackEvent(RatingContract, 'Rating').pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
// subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => x.rating)).subscribe((v) => {
eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), myscan, mymap).subscribe((v) => {
console.dir("value is ")
console.dir(v)
});
@ -47,10 +47,10 @@ async function run() {
return acc;
}, [])
// eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), max, distinctUntilChanged()).subscribe((v) => {
// eventSyncer.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), last()).subscribe((v) => {
// subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), max, distinctUntilChanged()).subscribe((v) => {
// subspace.trackEvent(RatingContract, 'Rating', ((x) => true)).pipe(map(x => parseInt(x.rating)), last()).subscribe((v) => {
eventSyncer.trackEvent(RatingContract, 'Rating').pipe(map(x => parseInt(x.rating)), max, distinctUntilChanged()).subscribe((v) => {
subspace.trackEvent(RatingContract, 'Rating').pipe(map(x => parseInt(x.rating)), max, distinctUntilChanged()).subscribe((v) => {
console.dir("max known rating is")
console.dir(v)
});

View File

@ -1,6 +1,7 @@
const { map, scan, last, distinctUntilChanged } = require('rxjs/operators');
const Web3Eth = require('web3-eth');
const {deployEscrowContract} = require('./utils-web3');
const Subspace = require('../dist/node.js');
let eth = new Web3Eth("ws://localhost:8545");
@ -14,7 +15,6 @@ let mymap = map(arr => arr.reduce((acc, current) => acc + current, 0) / arr.leng
async function run() {
let accounts = await eth.getAccounts();
var EscrowContract = await deployEscrowContract(eth)
console.dir(EscrowContract)
await EscrowContract.methods.createEscrow(1, accounts[0], accounts[1]).send({from: accounts[0]})
await EscrowContract.methods.createEscrow(1, accounts[1], accounts[2]).send({from: accounts[0]})
@ -27,15 +27,14 @@ async function run() {
// console.dir(event)
})
const EventSyncer = require('../dist/node.js');
const eventSyncer = new EventSyncer(eth.currentProvider);
const subspace = new Subspace(eth.currentProvider);
await eventSyncer.init()
await subspace.init()
console.dir("getting escrows created by " + accounts[0])
// eventSyncer.trackEvent(EscrowContract, 'Created', ((x) => true)).pipe().subscribe((v) => {
eventSyncer.trackEvent(EscrowContract, 'Created', { filter: { buyer: accounts[0] }, fromBlock: 1 }).pipe().subscribe((v) => {
// eventSyncer.trackEvent(EscrowContract, 'Rating', ((x) => true)).pipe(map(x => x.rating)).subscribe((v) => {
// subspace.trackEvent(EscrowContract, 'Created', ((x) => true)).pipe().subscribe((v) => {
subspace.trackEvent(EscrowContract, 'Created', { filter: { buyer: accounts[0] }, fromBlock: 1 }).pipe().subscribe((v) => {
// subspace.trackEvent(EscrowContract, 'Rating', ((x) => true)).pipe(map(x => x.rating)).subscribe((v) => {
console.dir("value is ")
console.dir(v)
});

View File

@ -1,5 +1,6 @@
const { map, scan, last, distinctUntilChanged } = require('rxjs/operators');
const Web3Eth = require('web3-eth');
const Subspace = require('../dist/node.js');
let eth = new Web3Eth("ws://localhost:8545");
@ -116,12 +117,11 @@ async function run() {
await SimpleStorageContract.methods.set(0, 300).send({ from: accounts[0] })
}, 2000)
const EventSyncer = require('../dist/node.js');
const eventSyncer = new EventSyncer(eth.currentProvider);
const subspace = new Subspace(eth.currentProvider);
await eventSyncer.init();
await subspace.init();
eventSyncer.trackProperty(SimpleStorageContract, 'get', [2], {from: "0x0000000000000000000000000000000000000012"} ).pipe().subscribe((v) => {
subspace.trackProperty(SimpleStorageContract, 'get', [2], {from: "0x0000000000000000000000000000000000000012"} ).pipe().subscribe((v) => {
console.dir("value is ")
console.dir(v)
})

View File

@ -1,5 +1,6 @@
const ganache = require("ganache-core");
const Web3Eth = require('web3-eth');
const Subspace = require('../dist/node.js');
console.log("The following error is emitted by ganache - https://github.com/trufflesuite/ganache-core/issues/267")
let eth = new Web3Eth(ganache.provider());
@ -13,12 +14,11 @@ async function run() {
await eth.sendTransaction({from: accounts[2], to: accounts[0], value: "232433434"});
}, 2000);
const EventSyncer = require('../dist/node.js');
const eventSyncer = new EventSyncer(eth.currentProvider);
const subspace = new Subspace(eth.currentProvider);
await eventSyncer.init();
await subspace.init();
eventSyncer.trackBalance(accounts[0]).subscribe((balance) => {
subspace.trackBalance(accounts[0]).subscribe((balance) => {
console.log("accounts[0] balance is ", balance);
})

View File

@ -1,4 +1,5 @@
const Web3Eth = require('web3-eth');
const Subspace = require('../dist/node.js');
let eth = new Web3Eth("ws://localhost:8545");
@ -55,11 +56,10 @@ async function run() {
console.dir(DummyERC20Token.options.address)
const EventSyncer = require('../dist/node.js');
const eventSyncer = new EventSyncer(eth.currentProvider);
const subspace = new Subspace(eth.currentProvider);
await subspace.init();
await eventSyncer.init();
eventSyncer.trackBalance(accounts[0], DummyERC20Token.options.address).pipe().subscribe((balance) => {
subspace.trackBalance(accounts[0], DummyERC20Token.options.address).pipe().subscribe((balance) => {
console.log("balance is ", balance)
});
}

View File

@ -1,5 +1,6 @@
const Web3Eth = require('web3-eth');
const {deployRatingContract, mine} = require('./utils-web3');
const Subspace = require('../dist/node.js');
const ganache = require("ganache-core");
console.log("The following error is emitted by ganache - https://github.com/trufflesuite/ganache-core/issues/267")
@ -32,40 +33,38 @@ async function run() {
await mine(eth);
await RatingContract.methods.doRating(8, 5).send({from: accounts[0]})
const EventSyncer = require('../dist/node.js');
const eventSyncer = new EventSyncer(eth.currentProvider);
await eventSyncer.init()
const subspace = new Subspace(eth.currentProvider);
await subspace.init()
// Testing single block with a event
eventSyncer.trackEvent(RatingContract, 'Rating', {fromBlock: 3, toBlock: 3}).subscribe((v) => {
subspace.trackEvent(RatingContract, 'Rating', {fromBlock: 3, toBlock: 3}).subscribe((v) => {
console.log("A", v)
});
// Testing blocks that have no events in between
eventSyncer.trackEvent(RatingContract, 'Rating', {fromBlock: 8, toBlock: 11}).subscribe((v) => {
subspace.trackEvent(RatingContract, 'Rating', {fromBlock: 8, toBlock: 11}).subscribe((v) => {
console.log("B", v)
});
// Testing blocks that begin with no events
eventSyncer.trackEvent(RatingContract, 'Rating', {fromBlock: 12, toBlock: 15}).subscribe((v) => {
subspace.trackEvent(RatingContract, 'Rating', {fromBlock: 12, toBlock: 15}).subscribe((v) => {
console.log("C", v)
});
// Testing all blocks
eventSyncer.trackEvent(RatingContract, 'Rating', {}).subscribe((v) => {
subspace.trackEvent(RatingContract, 'Rating', {}).subscribe((v) => {
console.log("D", v)
});
// Testing blocks that end in no events
eventSyncer.trackEvent(RatingContract, 'Rating', {fromBlock: 14, toBlock: 18}).subscribe((v) => {
subspace.trackEvent(RatingContract, 'Rating', {fromBlock: 14, toBlock: 18}).subscribe((v) => {
console.log("E", v)
});
setTimeout(() => {
// Testing if events come from the DB instead of a subscription
eventSyncer.trackEvent(RatingContract, 'Rating', {fromBlock: 7, toBlock: 11}).subscribe((v) => {
subspace.trackEvent(RatingContract, 'Rating', {fromBlock: 7, toBlock: 11}).subscribe((v) => {
console.log("E", v)
});
}, 5000);

View File

@ -1,17 +1,14 @@
const Web3Eth = require('web3-eth');
const Subspace = require('../dist/node.js');
let eth = new Web3Eth("wss://mainnet.infura.io/ws/v3/e62b6ada19b042ee9c6d68746b965ccf");
let eth = new Web3Eth("wss://mainnet.infura.io/ws/v3/_____________");
async function run() {
let accounts = await eth.getAccounts();
const EventSyncer = require('../dist/node.js');
const eventSyncer = new EventSyncer(eth.currentProvider);
await eventSyncer.init()
async function run() {
const subspace = new Subspace(eth.currentProvider);
await subspace.init()
// Testing single block with a event
eventSyncer.trackLogs({address: "0x744d70fdbe2ba4cf95131626614a1763df805b9e", topics: ["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", "0x00000000000000000000000068f47e153e1aa7d6529e078feff86eada87ddee3", null]}).subscribe((v) => {
subspace.trackLogs({address: "0x744d70fdbe2ba4cf95131626614a1763df805b9e", topics: ["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", "0x00000000000000000000000068f47e166e1aa7d6529e021feff86eada87aaee3", null]}).subscribe((v) => {
console.log(v);
});