Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

nomics-platform

Package Overview
Dependencies
Maintainers
3
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nomics-platform - npm Package Compare versions

Comparing version 0.13.4 to 0.13.5

3

lib/audit/au.js

@@ -110,3 +110,4 @@ const axios = require('axios')

try {
valid = (new Date(d.toISOString())).getTime() === d.getTime()
valid = new Date(d.toISOString()).getTime() === d.getTime()
valid = valid && o[p].slice(-1) === 'Z'
} catch (e) {

@@ -113,0 +114,0 @@ err = e.toString() + ' '

@@ -18,37 +18,43 @@ const au = require('../au')

info: async () => {
au.assertStringProperty(this.info, 'name')
au.assertStringProperty(this.info, 'description', { required: true })
try {
au.assertStringProperty(this.info, 'name')
au.assertStringProperty(this.info, 'description', { required: true })
if (!process.env.NOMICS_PLATFORM_RELAX) {
au.assert(this.info.description.length >= 1000, 'Expected description to be at least 1,000 characters')
if (!process.env.NOMICS_PLATFORM_RELAX) {
au.assert(this.info.description.length >= 1000, 'Expected description to be at least 1,000 characters')
au.assertStringProperty(this.info, 'location', { required: true })
au.assertURLProperty(this.info, 'logo', { required: true, https: true })
}
au.assertStringProperty(this.info, 'location', { required: true })
au.assertURLProperty(this.info, 'logo', { required: true, https: true })
}
au.assertURLProperty(this.info, 'website', { required: true })
au.assertStringProperty(this.info, 'twitter', { required: false })
if (au.assertProperty(this.info, 'capability', { required: false })) {
au.assertPropertyType(this.info, 'capability', 'object')
const capability = this.info.capability
au.assertBooleanProperty(capability, 'candles', { required: false })
au.assertBooleanProperty(capability, 'markets', { required: false })
au.assertBooleanProperty(capability, 'orders', { required: false })
au.assertBooleanProperty(capability, 'ordersSnapshot', { required: false })
au.assertBooleanProperty(capability, 'ordersSocket', { required: false })
au.assertBooleanProperty(capability, 'ticker', { required: false })
au.assertBooleanProperty(capability, 'trades', { required: false })
au.assertBooleanProperty(capability, 'tradesByTimestamp', { required: false })
au.assertBooleanProperty(capability, 'tradesSocket', { required: false })
au.assertURLProperty(this.info, 'website', { required: true })
au.assertStringProperty(this.info, 'twitter', { required: false })
if (au.assertProperty(this.info, 'capability', { required: false })) {
au.assertPropertyType(this.info, 'capability', 'object')
const capability = this.info.capability
au.assertBooleanProperty(capability, 'candles', { required: false })
au.assertBooleanProperty(capability, 'markets', { required: false })
au.assertBooleanProperty(capability, 'orders', { required: false })
au.assertBooleanProperty(capability, 'ordersSnapshot', { required: false })
au.assertBooleanProperty(capability, 'ordersSocket', { required: false })
au.assertBooleanProperty(capability, 'ticker', { required: false })
au.assertBooleanProperty(capability, 'trades', { required: false })
au.assertBooleanProperty(capability, 'tradesByTimestamp', { required: false })
au.assertBooleanProperty(capability, 'tradesSocket', { required: false })
}
au.assert(
this.info.capability.trades ||
this.info.capability.tradesByTimestamp ||
this.info.capability.orders ||
this.info.capability.ordersSnapshot ||
this.info.capability.ticker ||
this.info.capability.candles,
'Expected at least one data capability of trades, candles, orders, or ticker'
)
} catch (err) {
console.log(`FAILED: URL /info failed with "${err.message}"`)
throw err
}
au.assert(
this.info.capability.trades ||
this.info.capability.tradesByTimestamp ||
this.info.capability.orders ||
this.info.capability.ordersSnapshot ||
this.info.capability.ticker ||
this.info.capability.candles,
'Expected at least one data capability of trades, candles, orders, or ticker'
)
},

@@ -61,19 +67,31 @@

const data = await au.get('/markets')
try {
const data = await au.get('/markets')
au.assert(data.length > 0, 'Expected at least one market')
data.forEach(m => au.assertStringProperty(m, 'id'))
data.forEach(m => au.assertStringProperty(m, 'base', { required: false }))
data.forEach(m => au.assertStringProperty(m, 'quote', { required: false }))
au.assert(data.length > 0, 'Expected at least one market')
const idCounts = data.reduce((memo, m) => {
if (!memo[m.id]) {
memo[m.id] = 0
data.forEach(m => au.assertStringProperty(m, 'id'))
data.forEach(m => au.assertStringProperty(m, 'base'))
data.forEach(m => au.assertStringProperty(m, 'quote'))
if (!process.env.NOMICS_PLATFORM_RELAX) {
data.forEach(t => au.assertPropertyInSet(t, 'type', ['spot', 'future', 'option', 'derivative', 'index']))
data.forEach(m => au.assertBooleanProperty(m, 'active'))
}
memo[m.id]++
return memo
}, {})
Object.keys(idCounts).forEach(id => {
au.assert(idCounts[id] === 1, `Duplicate market ID: ${id}`)
})
const idCounts = data.reduce((memo, m) => {
if (!memo[m.id]) {
memo[m.id] = 0
}
memo[m.id]++
return memo
}, {})
Object.keys(idCounts).forEach(id => {
au.assert(idCounts[id] === 1, `Duplicate market ID: ${id}`)
})
} catch (err) {
console.log(`FAILED: URL /markets failed with "${err.message}"`)
throw err
}
},

@@ -104,2 +122,3 @@

au.assert(trades.length > 2, 'Expected more than two trades')
trades.forEach(t => au.assertStringProperty(t, 'id'))

@@ -174,7 +193,7 @@ trades.forEach(t => au.assertTimestampProperty(t, 'timestamp'))

!second.find(t => t.timestamp < trades[0].timestamp),
`Trades with since=${trades[0].id} contained a trade with a timestamp before the since parameter. Only trades *after or equal to* the since id should be returned`
`Trades with since=${trades[0].timestamp} contained a trade with a timestamp before the since parameter. Only trades *after or equal to* the since id should be returned`
)
au.assert(
second.find(t2 => t2.id === trades.find(t => t.timestamp > since).id),
`Trades with since=${trades[0].id} didn't contain an overlap with the first page. Expected to see trade with id ${trades[1].id}`
`Trades with since=${trades[0].timestamp} didn't contain an overlap with the first page. Expected to see trade with id ${trades[1].id}`
)

@@ -193,2 +212,41 @@

tradesSnapshot: async () => {
if (!this.info.capability || !this.info.capability.markets || !this.info.capability.tradesSnapshot) {
return
}
const markets = await au.get('/markets')
if (markets.length === 0) {
// If there are no markets, pass, since markets spec will fail
return
}
let success = false
let uri
for (let i = 0; i < markets.length && !success; i++) {
uri = null
try {
const market = markets[i]
uri = `/trades/snapshot?market=${encodeURIComponent(market.id)}`
const trades = await au.get(uri)
au.assert(trades.length > 2, 'Expected more than two trades')
trades.forEach(t => au.assertStringProperty(t, 'id'))
trades.forEach(t => au.assertTimestampProperty(t, 'timestamp'))
trades.forEach(t => au.assertNumericStringProperty(t, 'price'))
trades.forEach(t => au.assertNumericStringProperty(t, 'amount'))
trades.forEach(t => au.assertStringProperty(t, 'order', { required: false }))
trades.forEach(t => au.assertPropertyInSet(t, 'type', ['market', 'limit', 'ask', 'bid'], { required: false }))
trades.forEach(t => au.assertPropertyInSet(t, 'side', ['buy', 'sell'], { required: false }))
} catch (err) {
console.log(`FAILED: URL ${uri || err.stack} failed with "${err.message}"`)
throw err
}
}
},
ordersSnapshot: async () => {

@@ -279,82 +337,85 @@ if (!this.info.capability || !this.info.capability.markets || !this.info.capability.ordersSnapshot) {

const intervals = ['1d', '1h', '1m']
let uri
for (const interval of intervals) {
let candles
try {
for (const interval of intervals) {
uri = `/candles?market=${encodeURIComponent(market.id)}&interval=${interval}`
try {
candles = await au.get(`/candles?market=${encodeURIComponent(market.id)}&interval=${interval}`)
} catch (e) {
au.assert(false, `Expected to find candles endpoint for interval \`${interval}\``)
}
const candles = await au.get(uri)
const c = JSON.parse(JSON.stringify(candles)) // deep clone
let t = candles.map(c => c.timestamp)
let tSorted = c.map(c => c.timestamp).sort()
const c = JSON.parse(JSON.stringify(candles)) // deep clone
let t = candles.map(c => c.timestamp)
let tSorted = c.map(c => c.timestamp).sort()
au.assert(
JSON.stringify(t) === JSON.stringify(tSorted),
`Expected ${interval} candles to be sorted by timestamp ascending`
)
if (interval === '1d') {
au.assert(candles.length >= 7, 'Expected at least 7 1d candles')
au.assert(
new Date(candles[candles.length - 1].timestamp).getTime() > new Date().getTime() - 2 * DAY,
'Expected last 1d candle to be within the last 48 hours'
JSON.stringify(t) === JSON.stringify(tSorted),
`Expected ${interval} candles to be sorted by timestamp ascending`
)
}
if (interval === '1h') {
au.assert(candles.length >= 24, 'Expected at least 24 1h candles')
au.assert(
new Date(candles[candles.length - 1].timestamp).getTime() > new Date().getTime() - 2 * HOUR,
'Expected last 1h candle to be within the last 2 hours'
)
}
if (interval === '1m') {
au.assert(candles.length >= 60, 'Expected at least 60 1m candles')
au.assert(
new Date(candles[candles.length - 1].timestamp).getTime() > new Date().getTime() - 10 * MINUTE,
'Expected last 1m candle to be within the last 10 minutes'
)
}
candles.forEach(c => {
au.assertTimestampProperty(c, 'timestamp')
let date = new Date(c.timestamp)
if (interval === '1d') {
au.assert(date.getTime() % DAY === 0, 'Expected timestamp to aligned to day candle size in UTC')
au.assert(candles.length >= 7, 'Expected at least 7 1d candles')
au.assert(
new Date(candles[candles.length - 1].timestamp).getTime() > new Date().getTime() - 2 * DAY,
'Expected last 1d candle to be within the last 48 hours'
)
}
if (interval === '1h') {
au.assert(date.getTime() % HOUR === 0, 'Expected timestamp to aligned to hour candle size in UTC')
au.assert(candles.length >= 24, 'Expected at least 24 1h candles')
au.assert(
new Date(candles[candles.length - 1].timestamp).getTime() > new Date().getTime() - 2 * HOUR,
'Expected last 1h candle to be within the last 2 hours'
)
}
if (interval === '1d') {
au.assert(date.getTime() % MINUTE === 0, 'Expected timestamp to aligned to minute candle size in UTC')
if (interval === '1m') {
au.assert(candles.length >= 60, 'Expected at least 60 1m candles')
au.assert(
new Date(candles[candles.length - 1].timestamp).getTime() > new Date().getTime() - 10 * MINUTE,
'Expected last 1m candle to be within the last 10 minutes'
)
}
})
candles.forEach(c => {
au.assertNumericStringProperty(c, 'open')
candles.forEach(c => {
au.assertTimestampProperty(c, 'timestamp')
au.assertNumericStringProperty(c, 'high')
au.assert(parseFloat(c.high) >= parseFloat(c.open), 'Expected high to be greater than or equal to open')
au.assert(parseFloat(c.high) >= parseFloat(c.close), 'Expected high to be greater than or equal to close')
au.assert(parseFloat(c.high) >= parseFloat(c.low), 'Expected high to be greater than or equal to low')
let date = new Date(c.timestamp)
au.assertNumericStringProperty(c, 'low')
au.assert(parseFloat(c.low) > 0, 'Expected low to be greater than 0')
au.assert(parseFloat(c.low) <= parseFloat(c.open), 'Expected low to be less than or equal to open')
au.assert(parseFloat(c.low) <= parseFloat(c.close), 'Expected low to be less than or equal to close')
au.assert(parseFloat(c.low) <= parseFloat(c.high), 'Expected low to be less than or equal to high')
if (interval === '1d') {
au.assert(date.getTime() % DAY === 0, 'Expected timestamp to aligned to day candle size in UTC')
}
au.assertNumericStringProperty(c, 'close')
if (interval === '1h') {
au.assert(date.getTime() % HOUR === 0, 'Expected timestamp to aligned to hour candle size in UTC')
}
au.assertNumericStringProperty(c, 'volume')
au.assert(parseFloat(c.volume) >= 0, 'Expected volume to be greater than or equal to 0')
})
if (interval === '1d') {
au.assert(date.getTime() % MINUTE === 0, 'Expected timestamp to aligned to minute candle size in UTC')
}
})
candles.forEach(c => {
au.assertNumericStringProperty(c, 'open')
au.assertNumericStringProperty(c, 'high')
au.assert(parseFloat(c.high) >= parseFloat(c.open), 'Expected high to be greater than or equal to open')
au.assert(parseFloat(c.high) >= parseFloat(c.close), 'Expected high to be greater than or equal to close')
au.assert(parseFloat(c.high) >= parseFloat(c.low), 'Expected high to be greater than or equal to low')
au.assertNumericStringProperty(c, 'low')
au.assert(parseFloat(c.low) > 0, 'Expected low to be greater than 0')
au.assert(parseFloat(c.low) <= parseFloat(c.open), 'Expected low to be less than or equal to open')
au.assert(parseFloat(c.low) <= parseFloat(c.close), 'Expected low to be less than or equal to close')
au.assert(parseFloat(c.low) <= parseFloat(c.high), 'Expected low to be less than or equal to high')
au.assertNumericStringProperty(c, 'close')
au.assertNumericStringProperty(c, 'volume')
au.assert(parseFloat(c.volume) >= 0, 'Expected volume to be greater than or equal to 0')
})
}
} catch (err) {
console.log(`FAILED: URL ${uri || err.stack} failed with "${err.message}"`)
throw err
}

@@ -361,0 +422,0 @@ },

{
"name": "nomics-platform",
"version": "0.13.4",
"version": "0.13.5",
"description": "Nomics Platform Toolkit",

@@ -5,0 +5,0 @@ "keywords": [

@@ -16,3 +16,4 @@ # Nomics Platform

If data functionality needs to be audited prior to all metadata being available, you can use the `NOMICS_PLATFORM_RELAX`
environment variable to temporarily relax requirements for description length, logo URL, and location.
environment variable to temporarily relax requirements for description length, logo URL, and location. This flag will
also skip checks for markets `type` and `active` flags.

@@ -19,0 +20,0 @@ ```bash

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc