Skip to content
This repository was archived by the owner on Dec 21, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
"@types/uuid": "^8.3.0",
"@typescript-eslint/eslint-plugin": "^4.15.1",
"@typescript-eslint/parser": "^4.15.1",
"async-mutex": "^0.3.0",
"babel-loader": "^8.2.2",
"babel-plugin-add-module-exports": "^1.0.4",
"babel-plugin-transform-class-properties": "^6.24.1",
Expand Down Expand Up @@ -114,6 +113,7 @@
"@ethersproject/sha2": "^5.0.8",
"@ethersproject/transactions": "^5.0.10",
"@ethersproject/wallet": "^5.0.11",
"@ethersproject/web": "^5.0.13",
"debug": "^4.3.2",
"eventemitter3": "^4.0.7",
"lodash.uniqueid": "^4.0.1",
Expand Down
81 changes: 33 additions & 48 deletions src/Config.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,55 @@
import qs from 'qs'
import Debug from 'debug'
import { ControlLayer, MessageLayer } from 'streamr-client-protocol'
import { ExternalProvider, JsonRpcFetchFunc } from '@ethersproject/providers'
import { BigNumber } from '@ethersproject/bignumber'
import { O } from 'ts-toolbelt'
import { getVersionString, counterId } from './utils'
import { getVersionString } from './utils'
import { ConnectionInfo } from '@ethersproject/web'
import { Todo } from './types'

export type EthereumConfig = ExternalProvider|JsonRpcFetchFunc

export type StreamrClientOptions = {
id?: string
debug?: Debug.Debugger,
auth?: {
auth: {
privateKey?: string
ethereum?: EthereumConfig
apiKey?: string
username?: string
password?: string
}
url?: string
restUrl?: string
streamrNodeAddress?: string
autoConnect?: boolean
autoDisconnect?: boolean
orderMessages?: boolean,
retryResendAfter?: number,
gapFillTimeout?: number,
maxGapRequests?: number,
maxPublishQueueSize?: number,
publishWithSignature?: Todo,
verifySignatures?: Todo,
publisherStoreKeyHistory?: boolean,
groupKeys?: Todo
keyExchange?: Todo
mainnet?: Todo
sidechain?: {
url?: string
},
url: string
restUrl: string
streamrNodeAddress: string
autoConnect: boolean
autoDisconnect: boolean
orderMessages: boolean
retryResendAfter: number
gapFillTimeout: number
maxGapRequests: number
maxPublishQueueSize: number
publishWithSignature: Todo
verifySignatures: Todo
publisherStoreKeyHistory: boolean
groupKeys: Todo
keyExchange: Todo
mainnet?: ConnectionInfo|string
sidechain?: ConnectionInfo|string
dataUnion?: string
tokenAddress?: string,
minimumWithdrawTokenWei?: BigNumber|number|string,
sidechainTokenAddress?: string
factoryMainnetAddress?: string
factorySidechainAddress?: string
payForSignatureTransport?: boolean
cache?: {
maxSize?: number,
maxAge?: number
tokenAddress: string,
minimumWithdrawTokenWei?: BigNumber|number|string
factoryMainnetAddress: string
factorySidechainAddress: string
payForSignatureTransport: boolean
cache: {
maxSize: number,
maxAge: number
}
}

export type StreamrClientConfig = O.Compulsory<StreamrClientOptions, 'url' | 'restUrl'>
const { ControlMessage } = ControlLayer
const { StreamMessage } = MessageLayer

export default function ClientConfig(opts: Partial<StreamrClientOptions> = {}) {
const { id = counterId('StreamrClient') } = opts

const defaults = {
debug: Debug(id),
const defaults: StreamrClientOptions = {
// Authentication: identity used by this StreamrClient instance
auth: {}, // can contain member privateKey or (window.)ethereum

Expand Down Expand Up @@ -87,24 +77,19 @@ export default function ClientConfig(opts: Partial<StreamrClientOptions> = {}) {
// Ethereum and Data Union related options
// For ethers.js provider params, see https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#provider
mainnet: undefined, // Default to ethers.js default provider settings
sidechain: {
url: undefined, // TODO: add our default public service sidechain node, also find good PoA params below
// timeout:
// pollingInterval:
},
sidechain: undefined, // TODO: add our default public service sidechain node, also find good PoA params below
tokenAddress: '0x0Cf0Ee63788A0849fE5297F3407f701E122cC023',
minimumWithdrawTokenWei: '1000000', // Threshold value set in AMB configs, smallest token amount to pass over the bridge
sidechainTokenAddress: undefined, // TODO // sidechain token
factoryMainnetAddress: undefined, // TODO // Data Union factory that creates a new Data Union
factorySidechainAddress: undefined,
factoryMainnetAddress: 'TODO', // TODO // Data Union factory that creates a new Data Union
factorySidechainAddress: 'TODO',
payForSignatureTransport: true, // someone must pay for transporting the withdraw tx to mainnet, either us or bridge operator
cache: {
maxSize: 10000,
maxAge: 30 * 60 * 1000, // 30 minutes
}
}

const options: StreamrClientConfig = {
const options: StreamrClientOptions = {
...defaults,
...opts,
cache: {
Expand Down
18 changes: 4 additions & 14 deletions src/Connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,8 @@ async function OpenWebSocket(url, opts, ...args) {
})

// attach debug
if (opts && opts.debug) {
socket.debug = opts.debug.extend(socket.id)
socket.debug.color = opts.debug.color // use existing colour
} else {
socket.debug = Debug('StreamrClient::ws').extend(socket.id)
}
socket.debug = opts.debug.extend(socket.id)
socket.debug.color = opts.debug.color // use existing colour
} catch (err) {
reject(err)
}
Expand Down Expand Up @@ -292,15 +288,9 @@ export default class Connection extends EventEmitter {
}))
}

constructor(options = {}) {
constructor(options = {}, client) {
super()
const id = counterId(this.constructor.name)
/* istanbul ignore next */
if (options.debug) {
this._debug = options.debug.extend(id)
} else {
this._debug = Debug(`StreamrClient::${id}`)
}
this._debug = client.debug.extend(counterId(this.constructor.name))

this.options = options
this.options.autoConnect = !!this.options.autoConnect
Expand Down
58 changes: 39 additions & 19 deletions src/StreamrClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Debug from 'debug'

import { counterId, uuid, CacheAsyncFn } from './utils'
import { validateOptions } from './stream/utils'
import Config, { StreamrClientOptions, StreamrClientConfig } from './Config'
import Config, { StreamrClientOptions } from './Config'
import StreamrEthereum from './Ethereum'
import Session from './Session'
import Connection, { ConnectionError } from './Connection'
Expand All @@ -14,8 +14,10 @@ import { getUserId } from './user'
import { Todo, MaybeAsync } from './types'
import { StreamEndpoints } from './rest/StreamEndpoints'
import { LoginEndpoints } from './rest/LoginEndpoints'
import { DataUnionEndpoints } from './rest/DataUnionEndpoints'
import { DataUnion, DataUnionDeployOptions } from './dataunion/DataUnion'
import { BigNumber } from '@ethersproject/bignumber'
import { getAddress } from '@ethersproject/address'
import { Contract } from '@ethersproject/contracts'

// TODO get metadata type from streamr-protocol-js project (it doesn't export the type definitions yet)
export type OnMessageCallback = MaybeAsync<(message: any, metadata: any) => void>
Expand All @@ -32,8 +34,8 @@ export { StreamrClientOptions }

class StreamrConnection extends Connection {
// TODO define args type when we convert Connection class to TypeScript
constructor(...args: any) {
super(...args)
constructor(options: Todo, client: StreamrClient) {
super(options, client)
this.on('message', this.onConnectionMessage)
}

Expand Down Expand Up @@ -137,13 +139,13 @@ function Plugin(targetInstance: any, srcInstance: any) {
}

// these are mixed in via Plugin function above
interface StreamrClient extends StreamEndpoints, LoginEndpoints, DataUnionEndpoints {}
interface StreamrClient extends StreamEndpoints, LoginEndpoints {}

// eslint-disable-next-line no-redeclare
class StreamrClient extends EventEmitter {
id: string
debug: Debug.Debugger
options: StreamrClientConfig
options: StreamrClientOptions
session: Session
connection: StreamrConnection
publisher: Todo
Expand All @@ -152,18 +154,13 @@ class StreamrClient extends EventEmitter {
ethereum: StreamrEthereum
streamEndpoints: StreamEndpoints
loginEndpoints: LoginEndpoints
dataUnionEndpoints: DataUnionEndpoints

constructor(options: Partial<StreamrClientOptions> = {}, connection?: StreamrConnection) {
super()
this.id = counterId(`${this.constructor.name}:${uid}`)
this.debug = Debug(this.id)

this.options = Config({
id: this.id,
debug: this.debug,
...options,
})
this.options = Config(options)

this.debug('new StreamrClient %s: %o', this.id, {
version: process.env.version,
Expand All @@ -182,7 +179,7 @@ class StreamrClient extends EventEmitter {
this.on('error', this._onError) // attach before creating sub-components incase they fire error events

this.session = new Session(this, this.options.auth)
this.connection = connection || new StreamrConnection(this.options)
this.connection = connection || new StreamrConnection(this.options, this)

this.connection
.on('connected', this.onConnectionConnected)
Expand All @@ -195,7 +192,6 @@ class StreamrClient extends EventEmitter {

this.streamEndpoints = Plugin(this, new StreamEndpoints(this))
this.loginEndpoints = Plugin(this, new LoginEndpoints(this))
this.dataUnionEndpoints = Plugin(this, new DataUnionEndpoints(this))
this.cached = new StreamrCached(this)
}

Expand Down Expand Up @@ -380,18 +376,42 @@ class StreamrClient extends EventEmitter {
return this.getAddress()
}

/**
* Get token balance in "wei" (10^-18 parts) for given address
*/
async getTokenBalance(address: string): Promise<BigNumber> {
const { tokenAddress } = this.options
if (!tokenAddress) {
throw new Error('StreamrClient has no tokenAddress configuration.')
}
const addr = getAddress(address)
const provider = this.ethereum.getMainnetProvider()

const token = new Contract(tokenAddress, [{
name: 'balanceOf',
inputs: [{ type: 'address' }],
outputs: [{ type: 'uint256' }],
constant: true,
payable: false,
stateMutability: 'view',
type: 'function'
}], provider)
return token.balanceOf(addr)
}

getDataUnion(contractAddress: string) {
return new DataUnion(contractAddress, undefined, this.dataUnionEndpoints)
return DataUnion._fromContractAddress(contractAddress, this) // eslint-disable-line no-underscore-dangle
}

async deployDataUnion(options?: DataUnionDeployOptions) {
const contract = await this.dataUnionEndpoints.deployDataUnionContract(options)
return new DataUnion(contract.address, contract.sidechain.address, this.dataUnionEndpoints)
return DataUnion._deploy(options, this) // eslint-disable-line no-underscore-dangle
}

_getDataUnionFromName({ dataUnionName, deployerAddress }: { dataUnionName: string, deployerAddress: string}) {
const contractAddress = this.dataUnionEndpoints.calculateDataUnionMainnetAddress(dataUnionName, deployerAddress)
return this.getDataUnion(contractAddress)
return DataUnion._fromName({ // eslint-disable-line no-underscore-dangle
dataUnionName,
deployerAddress
}, this)
}

static generateEthereumAccount() {
Expand Down
Loading