Skip to content

Commit

Permalink
Merge pull request #218 from airgap-it/develop
Browse files Browse the repository at this point in the history
v2.2.8
  • Loading branch information
AndreasGassmann authored Jun 3, 2021
2 parents 170d0e8 + c8b3d38 commit 41ed641
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 38 deletions.
2 changes: 1 addition & 1 deletion 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
@@ -1,6 +1,6 @@
{
"name": "@airgap/beacon-sdk",
"version": "2.2.7",
"version": "2.2.8",
"description": "The beacon-sdk allows you to easily connect DApps with Wallets through P2P communication or a chrome extension.",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export const SDK_VERSION: string = '2.2.7'
export const SDK_VERSION: string = '2.2.8'
export const BEACON_VERSION: string = '2'
38 changes: 22 additions & 16 deletions src/matrix-client/MatrixClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ interface MatrixLoginConfig {
deviceId: string
}

const MAX_POLLING_RETRIES = 3
const IMMEDIATE_POLLING_RETRIES = 3
const RETRY_INTERVAL = 5000

/**
* The matrix client used to connect to the matrix network
Expand Down Expand Up @@ -200,15 +201,23 @@ export class MatrixClient {
*/
public unsubscribe(
event: MatrixClientEventType,
listener?: (event: MatrixClientEvent<any>) => void
listener: (event: MatrixClientEvent<any>) => void
): void {
if (listener) {
this.eventEmitter.removeListener(event, listener)
} else {
this.eventEmitter.removeAllListeners(event)
}
}

/**
* Unsubscribe from all matrix events of this type
*
* @param event
* @param listener
*/
public unsubscribeAll(event: MatrixClientEventType): void {
this.eventEmitter.removeAllListeners(event)
}

public async getRoomById(id: string): Promise<MatrixRoom> {
await this.isConnected()

Expand Down Expand Up @@ -317,29 +326,26 @@ export class MatrixClient {
resolve: (value?: void | PromiseLike<void> | undefined) => void,
reject: (reason?: any) => void
): Promise<void> => {
let continueSyncing: boolean = false
let syncingRetries: number = 0
try {
const response = await sync()
onSyncSuccess(response)

continueSyncing = true
} catch (error) {
onSyncError(error)

continueSyncing = store.get('pollingRetries') < MAX_POLLING_RETRIES
syncingRetries = store.get('pollingRetries')
// console.warn('Could not sync:', error)
if (continueSyncing && this.isActive) {
logger.log('Retry syncing...')
if (this.isActive) {
logger.log(`Retry syncing... ${syncingRetries} retries so far`)
}
} finally {
if (this.isActive) {
if (continueSyncing) {
setTimeout(async () => {
setTimeout(
async () => {
await pollSync(resolve, reject)
}, interval)
} else {
reject(new Error(`Max polling retries exeeded: ${MAX_POLLING_RETRIES}`))
}
},
syncingRetries > IMMEDIATE_POLLING_RETRIES ? RETRY_INTERVAL + interval : interval
)
} else {
reject(new Error(`Syncing stopped manually.`))
}
Expand Down
55 changes: 48 additions & 7 deletions src/transports/clients/P2PCommunicationClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ const logger = new Logger('P2PCommunicationClient')

const KNOWN_RELAY_SERVERS = ['matrix.papers.tech', 'beacon-node-0.papers.tech:8448']

const publicKeyToNumber = (arr: Uint8Array, mod: number) => {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i] + i
}
return Math.floor(sum % mod)
}

/**
* @internalapi
*
Expand Down Expand Up @@ -146,7 +154,7 @@ export class P2PCommunicationClient extends CommunicationClient {

console.log('GET RELAY SERVER')

const startIndex = Math.floor(Math.random() * this.KNOWN_RELAY_SERVERS.length)
const startIndex = publicKeyToNumber(this.keyPair.publicKey, this.KNOWN_RELAY_SERVERS.length)
let offset = 0

while (offset < this.KNOWN_RELAY_SERVERS.length) {
Expand Down Expand Up @@ -232,6 +240,7 @@ export class P2PCommunicationClient extends CommunicationClient {

if (member) {
await this.updateRelayServer(member)
await this.updatePeerRoom(member, event.content.roomId)
}
})

Expand Down Expand Up @@ -271,7 +280,11 @@ export class P2PCommunicationClient extends CommunicationClient {
await this.storage.delete(StorageKey.MATRIX_PEER_ROOM_IDS).catch((error) => logger.log(error))
await this.storage.delete(StorageKey.MATRIX_PRESERVED_STATE).catch((error) => logger.log(error))
await this.storage.delete(StorageKey.MATRIX_SELECTED_NODE).catch((error) => logger.log(error))
// Instead of resetting everything, maybe we should make sure a new instance is created?
this.relayServer = undefined
this.client = new ExposedPromise()
this.initialEvent = undefined
this.initialListener = undefined
}

public async listenForEncryptedMessage(
Expand All @@ -291,6 +304,7 @@ export class P2PCommunicationClient extends CommunicationClient {
let payload

await this.updateRelayServer(event.content.message.sender)
await this.updatePeerRoom(event.content.message.sender, event.content.roomId)

try {
payload = Buffer.from(event.content.message.content, 'hex')
Expand Down Expand Up @@ -337,8 +351,9 @@ export class P2PCommunicationClient extends CommunicationClient {
logger.log('listenForEncryptedMessage', 'No previous event found')
}

if (this.initialListener) {
;(await this.client.promise).unsubscribe(MatrixClientEventType.MESSAGE, this.initialListener)
const initialListener = this.initialListener
if (initialListener) {
;(await this.client.promise).unsubscribe(MatrixClientEventType.MESSAGE, initialListener)
}
this.initialListener = undefined
this.initialEvent = undefined
Expand All @@ -356,7 +371,7 @@ export class P2PCommunicationClient extends CommunicationClient {
}

public async unsubscribeFromEncryptedMessages(): Promise<void> {
;(await this.client.promise).unsubscribe(MatrixClientEventType.MESSAGE)
;(await this.client.promise).unsubscribeAll(MatrixClientEventType.MESSAGE)

this.activeListeners.clear()
}
Expand Down Expand Up @@ -404,6 +419,30 @@ export class P2PCommunicationClient extends CommunicationClient {
})
}

public async updatePeerRoom(sender: string, roomId: string): Promise<void> {
// Sender is in the format "@pubkeyhash:relayserver.tld"
const split = sender.split(':')
if (split.length < 2 || !split[0].startsWith('@')) {
throw new Error('Invalid sender')
}

const roomIds = await this.storage.get(StorageKey.MATRIX_PEER_ROOM_IDS)

const room = roomIds[sender]

if (room && room[1]) {
// If we have a room already, let's ignore it. We need to do this, otherwise it will be loaded from the matrix cache.
this.ignoredRooms.push(room[1])
}

roomIds[sender] = roomId

await this.storage.set(StorageKey.MATRIX_PEER_ROOM_IDS, roomIds)

// TODO: We also need to delete the room from the sync state
// If we need to delete a room, we can assume the local state is not up to date anymore, so we can reset the state
}

public async deleteRoomIdFromRooms(roomId: string): Promise<void> {
const roomIds = await this.storage.get(StorageKey.MATRIX_PEER_ROOM_IDS)
const newRoomIds = Object.entries(roomIds)
Expand All @@ -430,6 +469,7 @@ export class P2PCommunicationClient extends CommunicationClient {
logger.log(`listenForChannelOpening`, `channel opening`, JSON.stringify(event))

await this.updateRelayServer(event.content.message.sender)
await this.updatePeerRoom(event.content.message.sender, event.content.roomId)

const splits = event.content.message.content.split(':')
const payload = Buffer.from(splits[splits.length - 1], 'hex')
Expand Down Expand Up @@ -484,7 +524,10 @@ export class P2PCommunicationClient extends CommunicationClient {
const recipientHash = await getHexHash(Buffer.from(pairingRequest.publicKey, 'hex'))
const recipient = recipientString(recipientHash, pairingRequest.relayServer)

const roomId = await this.getRelevantRoom(recipient)
// We force room creation here because if we "re-pair", we need to make sure that we don't send it to an old room.
const roomId = await (await this.client.promise).createTrustedPrivateRoom(recipient)

await this.updatePeerRoom(recipient, roomId)

// Before we send the message, we have to wait for the join to be accepted.
await this.waitForJoin(roomId) // TODO: This can probably be removed because we are now waiting inside the get room method
Expand Down Expand Up @@ -527,7 +570,6 @@ export class P2PCommunicationClient extends CommunicationClient {
// Sender is in the format "@pubkeyhash:relayserver.tld"
const split = sender.split(':')
if (split.length < 2 || !split[0].startsWith('@')) {
console.log(sender)
throw new Error('Invalid sender')
}
const senderHash = split.shift()
Expand All @@ -539,7 +581,6 @@ export class P2PCommunicationClient extends CommunicationClient {
const promiseArray = (peers as any).map(
async (peer: P2PPairingRequest | ExtendedP2PPairingResponse) => {
const hash = `@${await getHexHash(Buffer.from(peer.publicKey, 'hex'))}`
console.log(hash, senderHash)
if (hash === senderHash) {
if (peer.relayServer !== relayServer) {
peer.relayServer = relayServer
Expand Down
28 changes: 17 additions & 11 deletions test/_helpers/_setup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,29 @@ const getVersionReply = () => {
}
}
}
const getLogin = (hostname: string) => {
console.log('GET LOGIN')
return {
user_id: `@xxx:${hostname}`,
access_token: 'ACCESS_TOKEN',
home_server: hostname,
device_id: 'xxx'
}
}
// const getLogin = (hostname: string) => {
// console.log('GET LOGIN')
// return {
// user_id: `@xxx:${hostname}`,
// access_token: 'ACCESS_TOKEN',
// home_server: hostname,
// device_id: 'xxx'
// }
// }

mock
.onGet('https://matrix.papers.tech/_matrix/client/versions')
.reply(200, getVersionReply())
.onGet('https://beacon-node-0.papers.tech:8448/_matrix/client/versions')
.reply(200, getVersionReply())
.onGet('/login')
.reply(200, getLogin('matrix.papers.tech'))
// .onPost('https://matrix.papers.tech/_matrix/client/r0/login')
// .reply(200, getLogin('matrix.papers.tech'))
// .onPost('https://beacon-node-0.papers.tech:8448/_matrix/client/r0/login')
// .reply(200, getLogin('beacon-node-0.papers.tech:8448'))
// .onGet('https://matrix.papers.tech/_matrix/client/r0/sync')
// .reply(200, {})
// .onGet('https://beacon-node-0.papers.tech:8448/_matrix/client/r0/sync')
// .reply(200, {})
.onAny()
.reply((config) => {
console.log('UNMOCKED URL, RETURNING ERROR 500', `${config.baseURL}${config.url}`)
Expand Down
7 changes: 6 additions & 1 deletion test/matrix-client/matrix-client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe(`MatrixClient`, () => {
const removeStub = sinon.stub((<any>client).eventEmitter, 'removeListener').resolves()
const removeAllStub = sinon.stub((<any>client).eventEmitter, 'removeAllListeners').resolves()

client.unsubscribe(MatrixClientEventType.MESSAGE)
client.unsubscribeAll(MatrixClientEventType.MESSAGE)

expect(removeStub.callCount).to.equal(0)
expect(removeAllStub.callCount).to.equal(1)
Expand Down Expand Up @@ -282,6 +282,11 @@ describe(`MatrixClient`, () => {
const successResponse = 'my-response'
const getStub = sinon.stub((<any>client).store, 'get').returns(3)
const syncStub = sinon.stub(client, <any>'sync').returns(successResponse)

// Stop the requests after 1s, otherwise it will retry forever
setTimeout(() => {
client.stop()
}, 1000)
;(<any>client)
.poll(
0,
Expand Down

0 comments on commit 41ed641

Please sign in to comment.