Skip to content
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
14 changes: 8 additions & 6 deletions .github/workflows/node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/setup-node@v2
- uses: actions/setup-node@v4
with:
node-version: "14.x"
node-version: "20.x"
cache: "npm"

- name: Install dependencies
Expand All @@ -27,15 +27,17 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/setup-node@v2
- uses: actions/setup-node@v4
with:
node-version: "14.x"
node-version: "20.x"
cache: "npm"

- name: Install dependencies
run: npm install

- name: Run tests
run: npm test
env:
ELECTRUM_API_KEY: ${{ secrets.ELECTRUM_API_KEY }}
4 changes: 2 additions & 2 deletions example/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ async function main() {
const client = new ElectrumClient(
'electrum.bitaroo.net',
50002,
'ssl'
'ssl',
)

try {
await client.connect(
'electrum-client-js', // optional client name
'1.4.2' // optional protocol version
'1.4.2', // optional protocol version
)

const header = await client.blockchain_headers_subscribe()
Expand Down
6 changes: 3 additions & 3 deletions src/electrum/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const util = require('./util')
const keepAliveInterval = 450 * 1000 // 7.5 minutes as recommended by ElectrumX SESSION_TIMEOUT

class ElectrumClient extends SocketClient {
constructor(host, port, protocol, options) {
super(host, port, protocol, options)
constructor(host, port, protocol, options, path) {
super(host, port, protocol, options, path)
}

async connect(clientName, electrumProtocolVersion, persistencePolicy = {maxRetry: 10, callback: null}) {
Expand Down Expand Up @@ -75,7 +75,7 @@ class ElectrumClient extends SocketClient {
}
},
keepAliveInterval,
this // pass this context as an argument to function
this, // pass this context as an argument to function
)
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/socket/socket_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ const TCPSocketClient = require('./socket_client_tcp')
const WebSocketClient = require('./socket_client_ws')

class SocketClient {
constructor(host, port, protocol, options) {
constructor(host, port, protocol, options, path) {
this.id = 0
this.host = host
this.port = port
this.protocol = protocol
this.options = options
this.path = path || ''
this.status = 0
this.callback_message_queue = {}
this.events = new EventEmitter()
Expand All @@ -27,7 +28,7 @@ class SocketClient {
break
case 'ws':
case 'wss':
this.client = new WebSocketClient(this, host, port, protocol, options)
this.client = new WebSocketClient(this, host, port, protocol, options, path)
break
default:
throw new Error(`invalid protocol: [${protocol}]`)
Expand Down
7 changes: 4 additions & 3 deletions src/socket/socket_client_ws.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
const W3CWebSocket = require('websocket').w3cwebsocket

class WebSocketClient {
constructor(self, host, port, protocol, options) {
constructor(self, host, port, protocol, options, path) {
this.self = self
this.host = host
this.port = port
this.protocol = protocol
this.options = options
this.path = path || ''
this.client = null
}

async connect() {
const url = `${this.protocol}://${this.host}:${this.port}`
const url = `${this.protocol}://${this.host}:${this.port}${this.path}`

// TODO: Add docs
// https://github.com/theturtle32/WebSocket-Node/blob/master/docs/W3CWebSocket.md#constructor
Expand All @@ -21,7 +22,7 @@ class WebSocketClient {
undefined,
undefined,
undefined,
this.options
this.options,
)

this.client = client
Expand Down
41 changes: 23 additions & 18 deletions test/config.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
const servers = {
tcp: {
protocol: 'tcp', port: '50001', host: 'electrum.bitaroo.net',
const ELECTRUM_API_KEY = process.env.ELECTRUM_API_KEY

const servers = [
{
protocol: 'tcp',
port: 50001,
host: 'electrum.bitaroo.net',
},
ssl: {
protocol: 'ssl', port: '50002', host: 'electrum.bitaroo.net',
{
protocol: 'ssl',
port: 50002,
host: 'electrum.bitaroo.net',
},
ws: {
protocol: 'ws', port: '50003', host: 'electrumx-server.tbtc.svc.cluster.local',
// no server available to test ws://
{
protocol: 'wss',
port: 8443,
host: 'electrumx-server.tbtc.network',
// FIXME: It's a temporary workaround to get the connection working.
options: {rejectUnauthorized: false},
},
wss: {
protocol: 'wss', port: '50004', host: 'electrumx-server.tbtc.svc.cluster.local',
{
protocol: 'wss',
port: 443,
host: 'electrum.mainnet.boar.network',
path: `/${ELECTRUM_API_KEY}`,
},
}

const serversArray = [
servers.tcp,
servers.ssl,
// FIXME: WebSocket is commented out for CI, until we find public servers for this protocol.
// electrumServers.ws,
// electrumServers.wss,
]

module.exports = {
servers,
serversArray,
}
105 changes: 51 additions & 54 deletions test/integration_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,76 +5,73 @@ const assert = chai.assert

const fs = require('fs')

const config = require('./config')
const {servers} = require('./config')

describe('ElectrumClient', async () => {
let txData

before(async () => {
txData = JSON.parse(await fs.readFileSync('./test/tx.json', 'utf8'))
txData = JSON.parse(fs.readFileSync('./test/tx.json', 'utf8'))
})

context('when connected', async () => {
config.serversArray.forEach((server) => {
describe(`for ${server.protocol} protocol`, async () => {
let client
describe('for all protocols', async () => {
servers.forEach((server) => {
const label = `${server.protocol}://${server.host}:${server.port}${server.path || ''}`
describe(label, async () => {
describe('when connected', async () => {
let client

before(async () => {
client = new ElectrumClient(
server.host,
server.port,
server.protocol,
server.options
)
before(async () => {
client = new ElectrumClient(
server.host,
server.port,
server.protocol,
server.options,
server.path,
)

await client
.connect('test_client' + server.protocol, '1.4.2')
.catch((err) => {
console.error(
`failed to connect with config [${JSON.stringify(
server
)}]: [${err}]`
)
})
})
await client.connect('test_client' + server.protocol, '1.4.2')
})

after(async () => {
await client.close()
})
after(async () => {
await client.close()
})

it('request returns result', async () => {
const expectedResult = txData.hex
const result = await client.blockchain_transaction_get(txData.hash)
it('request returns result', async () => {
const expectedResult = txData.hex
const result = await client.blockchain_transaction_get(txData.hash)

assert.equal(result, expectedResult, 'unexpected result')
assert.equal(result, expectedResult, 'unexpected result')
})
})
})
})
})

context('when not connected', async () => {
before(async () => {
const server = config.servers.tcp
describe('when not connected', async () => {
let client

client = new ElectrumClient(
server.host,
server.port,
server.protocol,
server.options
)
})
before(async () => {
client = new ElectrumClient(
server.host,
server.port,
server.protocol,
server.options,
server.path,
)
})

it('request throws error', async () => {
await client.blockchain_transaction_get(txData.hash).then(
(value) => {
// onFulfilled
assert.fail('not failed as expected')
},
(reason) => {
// onRejected
assert.include(reason.toString(), `connection not established`)
}
)
it('request throws error', async () => {
await client.blockchain_transaction_get(txData.hash).then(
(value) => {
// onFulfilled
assert.fail('not failed as expected')
},
(reason) => {
// onRejected
assert.include(reason.toString(), `connection not established`)
},
)
})
})
})
})
})
// TODO: Add tests
Expand Down
4 changes: 2 additions & 2 deletions test/tx.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"hash": "d60033c5cf5c199208a9c656a29967810c4e428c22efb492fdd816e6a0a1e548",
"hex": "010000000001011746bd867400f3494b8f44c24b83e1aa58c4f0ff25b4a61cffeffd4bc0f9ba300000000000ffffffff024897070000000000220020a4333e5612ab1a1043b25755c89b16d55184a42f81799e623e6bc39db8539c180000000000000000166a14edb1b5c2f39af0fec151732585b1049b07895211024730440220276e0ec78028582054d86614c65bc4bf85ff5710b9d3a248ca28dd311eb2fa6802202ec950dd2a8c9435ff2d400cc45d7a4854ae085f49e05cc3f503834546d410de012103732783eef3af7e04d3af444430a629b16a9261e4025f52bf4d6d026299c37c7400000000"
"hash": "a000b3082c3e177a5ba2064b74a87ef830f8107f3fb9f9274dde4ed79bb93008",
"hex": "02000000000103570412f893ca49eb1c42b6d22e385e8e281220eeb4b9526a77e3394a524a2bb80000000000ffffffffc7bf20bcf7643a91cb26410477a1066f1552c63b0f74175bb2a3169b2388cd2e0000000000ffffffffce1a14ab30f6e28ea6ee79469fed744b6b50c6e54583679da8ed00580bbe069f0300000000ffffffff0240420f0000000000220020f531e77ae36368687c262a7da1a89d7f22c48ab709cd83afe08e34c6db6952b90f4900000000000016001409da2b5bbfbe73460db900e09ec6745b65877c0b0248304502210095d6517ecaf5278c692ec72298088ac50f0e9f5afebd7418b4d8ad7cc59fa04202204bbb7c509344cee31982da546f01ab2cf2436425637769b1d4d9a4687ea4ff0601210387947b950113f035a5ffc732912670ebb34db4a97f6e3dd4ada2205b3994a2340248304502210090100e56b3c97b496fd9f9e83b31c26bd957be254826ff9bead8a95081e1851f02200c9d15825c4fa8ceb56828e8338b008791cb6d241f7f597e6587038aefb0aedb01210387947b950113f035a5ffc732912670ebb34db4a97f6e3dd4ada2205b3994a2340247304402204d1f7ba9de4889c9af06988de1142079f0f59ee3296b7acc5bb17cdda415260702200599898d448ee0798e9ced9eef059fc41d2a3c34b8526597d92655f64d6deacb01210387947b950113f035a5ffc732912670ebb34db4a97f6e3dd4ada2205b3994a23400000000"
}