-
Notifications
You must be signed in to change notification settings - Fork 262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/streams api #658
Feat/streams api #658
Changes from 2 commits
7fffd1e
25d0d7a
27f0d89
54ccbf6
662ff9a
dbd2aa9
8ef186c
3c487e5
7f99816
c815020
9eff875
28ee0da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
'@moralisweb3/api-utils': minor | ||
'@moralisweb3/core': minor | ||
'moralis': minor | ||
'@moralisweb3/streams': minor | ||
--- | ||
|
||
Intergrating stream API in code base, creating a new package @moralisweb3/streams |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export const MOCK_API_KEY = 'test-api-key'; | ||
export const EVM_API_ROOT = 'https://deep-index.moralis.io/api/v2'; | ||
export const SOL_API_ROOT = 'https://solana-gateway.moralis.io'; | ||
export const STREAM_API_ROOT = 'https://streams-api.aws-prod-streams-master-1.moralis.io'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { setupServer } from 'msw/node'; | ||
|
||
import { mockCreateStream } from './streamApi/createStream'; | ||
import { mockDeleteStream } from './streamApi/deleteStream'; | ||
import { mockGetStreams } from './streamApi/getStreams'; | ||
import { mockUpdateStream } from './streamApi/updateStream'; | ||
import { mockSetSettings } from './streamApi/setSettings'; | ||
import { mockGetSettings } from './streamApi/getSettings'; | ||
|
||
const handlers = [ | ||
mockCreateStream, | ||
mockGetStreams, | ||
mockUpdateStream, | ||
mockDeleteStream, | ||
mockSetSettings, | ||
mockGetSettings, | ||
]; | ||
|
||
export const mockServer = setupServer(...handlers); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { rest } from 'msw'; | ||
import { STREAM_API_ROOT, MOCK_API_KEY } from '../config'; | ||
|
||
export const mockCreateStreamOutput: Record<string, string> = { | ||
address: '0x992eCcC191D6F74E8Be187ed6B6AC196b08314f7', | ||
chainId: '0x3', | ||
}; | ||
|
||
export const mockCreateStream = rest.put(`${STREAM_API_ROOT}/streams`, (req, res, ctx) => { | ||
const apiKey = req.headers.get('x-api-key'); | ||
|
||
if (apiKey !== MOCK_API_KEY) { | ||
return res(ctx.status(401)); | ||
} | ||
|
||
const value = mockCreateStreamOutput; | ||
|
||
if (!value) { | ||
return res(ctx.status(404)); | ||
} | ||
|
||
return res(ctx.status(200), ctx.json(value)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should create mocks based on a real API response. Check this file: That allows us to create better integration tests: |
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { rest } from 'msw'; | ||
import { STREAM_API_ROOT, MOCK_API_KEY } from '../config'; | ||
|
||
export const mockDeleteStreamOutput: Record<string, string> = { | ||
'3fa85f64-5717-4562-b3fc-2c963f66afa6': '0x3', | ||
}; | ||
|
||
export const mockDeleteStream = rest.delete(`${STREAM_API_ROOT}/streams/:id`, (req, res, ctx) => { | ||
const id = req.params.id as string; | ||
const apiKey = req.headers.get('x-api-key'); | ||
|
||
if (apiKey !== MOCK_API_KEY) { | ||
return res(ctx.status(401)); | ||
} | ||
|
||
const value = mockDeleteStreamOutput[id]; | ||
|
||
if (!value) { | ||
return res(ctx.status(404)); | ||
} | ||
|
||
return res( | ||
ctx.status(200), | ||
ctx.json({ | ||
chainId: value, | ||
}), | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs a real response mock. |
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { rest } from 'msw'; | ||
import { STREAM_API_ROOT, MOCK_API_KEY } from '../config'; | ||
|
||
export const mockGetSettingsOutput: Record<string, string> = { | ||
secretKey: 'top_secret', | ||
region: 'us-east-1', | ||
}; | ||
|
||
export const mockGetSettings = rest.get(`${STREAM_API_ROOT}/settings`, (req, res, ctx) => { | ||
const apiKey = req.headers.get('x-api-key'); | ||
|
||
if (apiKey !== MOCK_API_KEY) { | ||
return res(ctx.status(401)); | ||
} | ||
|
||
const value = mockGetSettingsOutput; | ||
|
||
if (!value) { | ||
return res(ctx.status(404)); | ||
} | ||
|
||
return res(ctx.status(200), ctx.json(value)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs a real response mock. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
is a real response for this endpoint There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see.
This condition is always false. |
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { rest } from 'msw'; | ||
import { STREAM_API_ROOT, MOCK_API_KEY } from '../config'; | ||
|
||
export const mockGetStreamsOutput = 20; | ||
|
||
export const mockGetStreams = rest.get(`${STREAM_API_ROOT}/streams`, (req, res, ctx) => { | ||
const apiKey = req.headers.get('x-api-key'); | ||
|
||
if (apiKey !== MOCK_API_KEY) { | ||
return res(ctx.status(401)); | ||
} | ||
|
||
const value = mockGetStreamsOutput; | ||
|
||
if (!value) { | ||
return res(ctx.status(404)); | ||
} | ||
|
||
return res( | ||
ctx.status(200), | ||
ctx.json({ | ||
total: value, | ||
}), | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs a real response mock. |
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { rest } from 'msw'; | ||
import { STREAM_API_ROOT, MOCK_API_KEY } from '../config'; | ||
|
||
export const mockSetSettingsOutput: Record<string, string> = {}; | ||
|
||
export const mockSetSettings = rest.post(`${STREAM_API_ROOT}/settings`, (req, res, ctx) => { | ||
const apiKey = req.headers.get('x-api-key'); | ||
|
||
if (apiKey !== MOCK_API_KEY) { | ||
return res(ctx.status(401)); | ||
} | ||
|
||
const value = mockSetSettingsOutput; | ||
|
||
if (!value) { | ||
return res(ctx.status(404)); | ||
} | ||
|
||
return res(ctx.status(200), ctx.json(value)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs a real response mock. |
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { rest } from 'msw'; | ||
import { STREAM_API_ROOT, MOCK_API_KEY } from '../config'; | ||
|
||
export const mockUpdateStreamOutput: Record<string, string> = { | ||
'3fa85f64-5717-4562-b3fc-2c963f66afa6': '0x3', | ||
}; | ||
|
||
export const mockUpdateStream = rest.post(`${STREAM_API_ROOT}/streams/:id`, (req, res, ctx) => { | ||
const id = req.params.id as string; | ||
const apiKey = req.headers.get('x-api-key'); | ||
|
||
if (apiKey !== MOCK_API_KEY) { | ||
return res(ctx.status(401)); | ||
} | ||
|
||
const value = mockUpdateStreamOutput[id]; | ||
|
||
if (!value) { | ||
return res(ctx.status(404)); | ||
} | ||
|
||
return res( | ||
ctx.status(200), | ||
ctx.json({ | ||
chainId: value, | ||
}), | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs a real response mock. |
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { MoralisStreams } from '@moralisweb3/streams'; | ||
import { cleanStreamsApi, setupStreamApi } from './setup'; | ||
|
||
describe('Create stream', () => { | ||
let StreamApi: MoralisStreams; | ||
|
||
beforeAll(() => { | ||
StreamApi = setupStreamApi(); | ||
}); | ||
|
||
afterAll(() => { | ||
cleanStreamsApi(); | ||
}); | ||
|
||
it('should create a stream ', async () => { | ||
const result = await StreamApi.add({ | ||
chainId: '0x3', | ||
address: '0x992eCcC191D6F74E8Be187ed6B6AC196b08314f7', | ||
tag: 'test', | ||
description: 'test', | ||
type: 'tx', | ||
webhookUrl: 'https://webhook.site/4f1b1b1b-1b1b-4f1b-1b1b-1b1b1b1b1b1b', | ||
}); | ||
|
||
expect(result).toBeDefined(); | ||
expect(result).toEqual(expect.objectContaining({})); | ||
expect(result.result.chainId).toEqual('0x3'); | ||
}); | ||
|
||
it('should not create stream', async () => { | ||
const failedResult = await StreamApi.add({ | ||
chainId: 'invalid_chain', | ||
address: '0x992eCcC191D6F74E8Be187ed6B6AC196b08314f7', | ||
tag: 'test', | ||
description: 'test', | ||
type: 'tx', | ||
webhookUrl: 'https://webhook.site/4f1b1b1b-1b1b-4f1b-1b1b-1b1b1b1b1b1b', | ||
}) | ||
.then() | ||
.catch((err: any) => { | ||
return err; | ||
}); | ||
|
||
expect(failedResult).toBeDefined(); | ||
expect( | ||
StreamApi.add({ | ||
chainId: 'invalid_chain', | ||
address: '0x992eCcC191D6F74E8Be187ed6B6AC196b08314f7', | ||
tag: 'test', | ||
description: 'test', | ||
type: 'tx', | ||
webhookUrl: 'https://webhook.site/4f1b1b1b-1b1b-4f1b-1b1b-1b1b1b1b1b1b', | ||
}), | ||
).rejects.toThrowErrorMatchingInlineSnapshot( | ||
`"[C0005] Invalid provided chain, value must be a positive number, or a hex-string starting with '0x'"`, | ||
); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { MoralisStreams } from '@moralisweb3/streams'; | ||
import { cleanStreamsApi, setupStreamApi } from './setup'; | ||
|
||
describe('Delete stream', () => { | ||
let StreamApi: MoralisStreams; | ||
|
||
beforeAll(() => { | ||
StreamApi = setupStreamApi(); | ||
}); | ||
|
||
afterAll(() => { | ||
cleanStreamsApi(); | ||
}); | ||
|
||
it('should delete a stream ', async () => { | ||
const result = await StreamApi.delete({ | ||
id: '3fa85f64-5717-4562-b3fc-2c963f66afa6', | ||
}); | ||
|
||
expect(result).toBeDefined(); | ||
expect(result).toEqual(expect.objectContaining({})); | ||
expect(result.result.chainId).toEqual('0x3'); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { MoralisStreams } from '@moralisweb3/streams'; | ||
import { cleanStreamsApi, setupStreamApi } from './setup'; | ||
|
||
describe('Get settings', () => { | ||
let StreamApi: MoralisStreams; | ||
|
||
beforeAll(() => { | ||
StreamApi = setupStreamApi(); | ||
}); | ||
|
||
afterAll(() => { | ||
cleanStreamsApi(); | ||
}); | ||
|
||
it('should get stream settings ', async () => { | ||
const result = await StreamApi.readSettings(); | ||
|
||
expect(result).toBeDefined(); | ||
expect(result).toEqual(expect.objectContaining({})); | ||
expect(result.result.region).toEqual('us-east-1'); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should request the API squad to normalize this property? Here should be also
result
as everywhere.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, to have consistency across Moralis Apis. @ErnoW what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the best option. Otherwise we should modify the PaginatedEndpoint interface. The current state is wrong. We don't have
result
anddata
in the same type as the definition says.