Skip to content

Commit

Permalink
add v0.6.0 changes from individual repos
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrouid committed Sep 2, 2018
1 parent faba895 commit dd6515c
Show file tree
Hide file tree
Showing 13 changed files with 376 additions and 176 deletions.
2 changes: 1 addition & 1 deletion packages/walletconnect-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "js-walletconnect-core",
"version": "0.5.0",
"version": "0.6.0",
"description": "Walletconnect core library",
"scripts": {
"clean": "rm -rf dist",
Expand Down
125 changes: 106 additions & 19 deletions packages/walletconnect-core/src/connector.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
/* global fetch */

import crypto from 'crypto'
import { Buffer } from 'safe-buffer'
import { Buffer } from 'buffer'
import Ajv from 'ajv'

import generateKey from './generate-key'
import URLTransactionRequest from './url-transaction-request'
import generateKey from './generateKey'
import parseStandardURI from './parseStandardURI'
import URLTransactionRequest from './url_transaction_request'

const AES_ALGORITHM = 'AES-256-CBC'
const HMAC_ALGORITHM = 'SHA256'
Expand Down Expand Up @@ -90,7 +89,7 @@ export default class Connector {
type: 'object',
properties: {
name: { type: 'string' },
type: { type: 'string', enum: this.solidityTypes }
type: { type: 'string', enum: this._solidityTypes }
},
required: ['name', 'type']
}
Expand Down Expand Up @@ -193,44 +192,132 @@ export default class Connector {
return URLTransactionRequest.encode(tx)
}

// -- Private --------------------------------------------------------------- //

//
// Private methods
// Format ERC-1328 URI Format
//
_formatURI() {
const _sharedKey = Buffer.from(this.sharedKey, 'hex')
const symKey = _sharedKey.toString('base64')
const uri = `ethereum:wc-${this.sessionId}@1?name=${this.dappName}&bridge=${
this.bridgeUrl
}&symKey=${symKey}`
return uri
}

//
// Get encryptedData remote data
// Parse ERC-1328 URI Format
//
_parseURI(string) {
const standardURI = parseStandardURI(string)
if (standardURI.prefix && standardURI.prefix === 'wc') {
const uri = {
protocol: standardURI.protocol,
version: standardURI.version,
sessionID: standardURI.sessionID,
bridgeUrl: standardURI.bridge,
dappName: standardURI.name,
sharedKey: Buffer.from(standardURI.symKey, 'base64').toString('hex')
}
return uri
} else {
throw new Error(`URI doesn't follow ERC-1328 standard`)
}
}

//
// Fetch Bridge Payload
//

async _fetchBridge(url, headers = null, body = null) {
const requestUrl = `${this.bridgeUrl}${url}`

async _getEncryptedData(url, withTtl = false) {
const res = await fetch(`${this.bridgeUrl}${url}`, {
method: 'GET',
const config = {
headers: {
method: 'GET',
Accept: 'application/json',
'Content-Type': 'application/json'
}
})
}

if (headers) {
config.headers = { ...config.headers, ...headers }
}

if (body) {
config.body = JSON.stringify(body)
}

const res = await fetch(requestUrl, config)

// check for no content
if (res.status === 204) {
return null
}

// check for error message
if (res.status >= 400) {
throw new Error(res.statusText)
}

// get body
const body = await res.json()
const response = await res.json()

const decryptedData = this.decrypt(body.data).data
if (withTtl) {
return { data: decryptedData, ttlInSeconds: body.ttlInSeconds }
} else {
return decryptedData
return response
}

_decryptPayload(data) {
let decryptedData = data
if (data.encryptionPayload) {
decryptedData.data = this.decrypt(data.encryptionPayload).data
delete decryptedData.encryptionPayload
}
return decryptedData
}

get solidityTypes() {
//
// Get encrypted remote data
//

async _getEncryptedData(url) {
const response = this._fetchBridge(url)

const { data } = response

const decryptedData = this._decryptPayload(data)
return decryptedData
}

//
// Get multiple encrypted remote data
//

async _getMultipleEncryptedData(url) {
const response = this._fetchBridge(url)

const { data } = response

let decryptedData

if (Array.isArray(data)) {
decryptedData = data.map(payload => this._decryptPayload(payload))
} else if (typeof data === 'object') {
decryptedData = {}
Object.keys(data).forEach(key => {
const payload = this._decryptPayload(data[key])
decryptedData[key] = payload
})
}

return decryptedData
}

//
// Get solidityTypes
//

get _solidityTypes() {
const types = ['bool', 'address', 'int', 'uint', 'string', 'byte']
const ints = Array.from(new Array(32)).map(
(e, index) => `int${(index + 1) * 8}`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global Promise */

import crypto from 'crypto'

export default async function generateKey(n = 256 / 8) {
Expand Down
6 changes: 4 additions & 2 deletions packages/walletconnect-core/src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'idempotent-babel-polyfill'

import Connector from './connector'
import Listener from './listener'
import generateKey from './generate-key'
import generateKey from './generateKey'

export default { Connector, Listener, generateKey }
export { Connector, Listener, generateKey }
6 changes: 1 addition & 5 deletions packages/walletconnect-core/src/listener.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global setTimeout clearTimeout */

export default class Listener {
// options => fn, cb, timeout, pollInterval
constructor(connector, options = {}) {
Expand Down Expand Up @@ -33,9 +31,7 @@ export default class Listener {
this._success = true
this.options.cb(null, result)
}
} catch (e) {
// continue regardless of error
}
} catch (e) {}
}

stop() {
Expand Down
71 changes: 71 additions & 0 deletions packages/walletconnect-core/src/parseStandardURI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Parse EIP681 and EIP1328 standard URI formats
// (c) Pedro Gomes <pedrouid@protonmail.com>
// MIT License

function parseRequiredParams(path, prefix, keys) {
const required = { prefix }
path = path.replace(`${prefix}-`, '')
const values = path.split('@')
keys.forEach((key, idx) => (required[key] = values[idx] || ''))
return required
}

function parseParamsString(paramsString) {
if (!paramsString) return {}

let parameters = {}

let pairs = (paramsString[0] === '?'
? paramsString.substr(1)
: paramsString
).split('&')

for (let i = 0; i < pairs.length; i++) {
const key = pairs[i].match(/\w+(?==)/i)
? pairs[i].match(/\w+(?==)/i)[0]
: null
const value = pairs[i].match(/=.+/i)
? pairs[i].match(/=.+/i)[0].substr(1)
: ''
if (key) {
parameters[decodeURIComponent(key)] = decodeURIComponent(value)
}
}
return parameters
}

function parseStandardURI(string) {
if (!string || typeof string !== 'string') {
throw new Error('URI is not a string')
}

const pathStart = string.indexOf(':')

const pathEnd = string.indexOf('?')

const protocol = string.substring(0, pathStart)

let required = {}

let path =
string.indexOf('?') !== -1
? string.substring(pathStart + 1, pathEnd)
: string.substring(pathStart + 1)

if (path.startsWith('pay')) {
required = parseRequiredParams(path, 'pay', ['targetAddress', 'chainID'])
} else if (path.startsWith('wc')) {
required = parseRequiredParams(path, 'wc', ['sessionID', 'version'])
} else {
throw new Error('URI missing prefix')
}

const paramsString =
string.indexOf('?') !== -1 ? string.substring(pathEnd) : ''

const parameters = parseParamsString(paramsString)

return { protocol, ...required, ...parameters }
}

export default parseStandardURI
101 changes: 101 additions & 0 deletions packages/walletconnect-core/src/parseStandardURIwithFallback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Parse EIP681 and EIP1328 standard URI formats
// (c) Pedro Gomes <pedrouid@protonmail.com>
// MIT License

function parseRequiredParams(path, prefix, keys) {
const required = { prefix }
path = path.replace(`${prefix}-`, '')
const values = path.split('@')
keys.forEach((key, idx) => (required[key] = values[idx] || ''))
return required
}

function parseRequiredFallback(path) {
let required = {}
let prefix = ''
const values = path.split('@')
values.forEach((value, idx) => {
if (idx === 0) {
if (
value.match(
/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i
)
) {
prefix = 'wc'
required.prefix = prefix
required.sessionID = value
} else {
prefix = 'pay'
required.prefix = prefix
required.targetAddress = value
}
} else if (idx === 1) {
if (prefix === 'wc') {
required.version = value
} else if (prefix === 'pay') {
required.chainID = value
}
}
})
return required
}

function parseParamsString(paramsString) {
if (!paramsString) return {}

let parameters = {}

let pairs = (paramsString[0] === '?'
? paramsString.substr(1)
: paramsString
).split('&')

for (let i = 0; i < pairs.length; i++) {
const key = pairs[i].match(/\w+(?==)/i)
? pairs[i].match(/\w+(?==)/i)[0]
: null
const value = pairs[i].match(/=.+/i)
? pairs[i].match(/=.+/i)[0].substr(1)
: ''
if (key) {
parameters[decodeURIComponent(key)] = decodeURIComponent(value)
}
}
return parameters
}

function parseStandardURIwithFallback(string) {
if (!string || typeof string !== 'string') {
throw new Error('URI is not a string')
}

const pathStart = string.indexOf(':')

const pathEnd = string.indexOf('?')

const protocol = string.substring(0, pathStart)

let required = {}

let path =
string.indexOf('?') !== -1
? string.substring(pathStart + 1, pathEnd)
: string.substring(pathStart + 1)

if (path.startsWith('pay')) {
required = parseRequiredParams(path, 'pay', ['targetAddress', 'chainID'])
} else if (path.startsWith('wc')) {
required = parseRequiredParams(path, 'wc', ['sessionID', 'version'])
} else {
required = parseRequiredFallback(path)
}

const paramsString =
string.indexOf('?') !== -1 ? string.substring(pathEnd) : ''

const parameters = parseParamsString(paramsString)

return { protocol, ...required, ...parameters }
}

export default parseStandardURIwithFallback

0 comments on commit dd6515c

Please sign in to comment.