-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* adds rate limiting on all routes, adds redis and related config for rate limiter * adds first route tests and server test helper, adds isPubKey validator * fixes ledger key generator for token balance, adds mode env var * adds test for account balances route * updates balance key to use symbol instead of string * updates test ledger key
- Loading branch information
1 parent
b142c0e
commit 8d450a0
Showing
13 changed files
with
346 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
version: "3.9" | ||
services: | ||
redis: | ||
image: redis:7.2-alpine | ||
container_name: freighter-redis | ||
hostname: freighter-redis | ||
restart: always | ||
networks: | ||
- freighter | ||
ports: | ||
- 6379:6379 | ||
|
||
networks: | ||
freighter: | ||
driver: bridge |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ import pino from "pino"; | |
|
||
import { mutation, query } from "../service/mercury/queries"; | ||
import { MercuryClient } from "../service/mercury"; | ||
import { initApiServer } from "../route"; | ||
|
||
const testLogger = pino({ | ||
name: "test-logger", | ||
|
@@ -37,9 +38,9 @@ const mercurySession = { | |
userId: "1", | ||
}; | ||
|
||
const pubKey = "GDUBMXMABE7UOZSGYJ5ONE7UYAEHKK3JOX7HZQGNZ7NYTZPPP4AJ2GQJ"; | ||
const pubKey = "GCGORBD5DB4JDIKVIA536CJE3EWMWZ6KBUBWZWRQM7Y3NHFRCLOKYVAL"; | ||
const tokenBalanceLedgerKey = | ||
"AAAAEAAAAAEAAAABAAAAEQAAAAEAAAACAAAADwAAAAdiYWxhbmNlAAAAAA4AAAAHQmFsYW5jZQAAAAAPAAAAB2FkZHJlc3MAAAAADgAAADhHRFVCTVhNQUJFN1VPWlNHWUo1T05FN1VZQUVIS0szSk9YN0haUUdOWjdOWVRaUFBQNEFKMkdRSg=="; | ||
"AAAAEAAAAAEAAAACAAAADwAAAAdCYWxhbmNlAAAAABIAAAAAAAAAAIzohH0YeJGhVUA7vwkk2SzLZ8oNA2zaMGfxtpyxEtys"; | ||
|
||
const queryMockResponse = { | ||
[mutation.authenticate]: { | ||
|
@@ -59,7 +60,8 @@ const queryMockResponse = { | |
edges: [ | ||
{ | ||
node: { | ||
contractId: "contract-id-1", | ||
contractId: | ||
"CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP", | ||
keyXdr: tokenBalanceLedgerKey, | ||
valueXdr: "value-xdr", | ||
ledgerTimestamp: "timestamp", | ||
|
@@ -69,7 +71,8 @@ const queryMockResponse = { | |
}, | ||
{ | ||
node: { | ||
contractId: "contract-id-2", | ||
contractId: | ||
"CBGTG7XFRY3L6OKAUTR6KGDKUXUQBX3YDJ3QFDYTGVMOM7VV4O7NCODG", | ||
keyXdr: tokenBalanceLedgerKey, | ||
valueXdr: "value-xdr", | ||
ledgerTimestamp: "timestamp", | ||
|
@@ -100,7 +103,7 @@ const queryMockResponse = { | |
assetNative: true, | ||
accountBySource: { | ||
publickey: | ||
"GCGORBD5DB4JDIKVIA536CJE3EWMWZ6KBUBWZWRQM7Y3NHFRCLOKYVAL", | ||
"CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP", | ||
}, | ||
accountByDestination: { | ||
publickey: pubKey, | ||
|
@@ -133,8 +136,16 @@ jest.spyOn(client, "query").mockImplementation((_query: any): any => { | |
}); | ||
} | ||
case query.getAccountBalances(tokenBalanceLedgerKey, [ | ||
"contract-id-1", | ||
"contract-id-2", | ||
"CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP", | ||
]): { | ||
return Promise.resolve({ | ||
data: queryMockResponse["query.getAccountBalances"], | ||
error: null, | ||
}); | ||
} | ||
case query.getAccountBalances(tokenBalanceLedgerKey, [ | ||
"CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP", | ||
"CBGTG7XFRY3L6OKAUTR6KGDKUXUQBX3YDJ3QFDYTGVMOM7VV4O7NCODG", | ||
]): { | ||
return Promise.resolve({ | ||
data: queryMockResponse["query.getAccountBalances"], | ||
|
@@ -147,5 +158,27 @@ jest.spyOn(client, "query").mockImplementation((_query: any): any => { | |
}); | ||
|
||
const mockMercuryClient = new MercuryClient(mercurySession, client, testLogger); | ||
|
||
export { pubKey, mockMercuryClient, queryMockResponse }; | ||
async function getDevServer() { | ||
const config = { | ||
hostname: "localhost", | ||
mode: "development", | ||
mercuryEmail: "[email protected]", | ||
mercuryKey: "xxx", | ||
mercuryPassword: "pass", | ||
mercuryBackend: "backend", | ||
mercuryGraphQL: "graph-ql", | ||
mercuryUserId: "user-id", | ||
redisConnectionName: "freighter", | ||
redisPort: 6379, | ||
}; | ||
const server = initApiServer(mockMercuryClient, config); | ||
await server.listen(); | ||
return server; | ||
} | ||
export { | ||
pubKey, | ||
mockMercuryClient, | ||
queryMockResponse, | ||
getDevServer, | ||
tokenBalanceLedgerKey, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { getDevServer, queryMockResponse, pubKey } from "../helper/test-helper"; | ||
import { query } from "../service/mercury/queries"; | ||
|
||
describe("API routes", () => { | ||
describe("/account-history/:pubKey", () => { | ||
it("can fetch an account history for a pub key", async () => { | ||
const server = await getDevServer(); | ||
const response = await fetch( | ||
`http://localhost:${ | ||
(server?.server?.address() as any).port | ||
}/api/v1/account-history/${pubKey}` | ||
); | ||
const { data } = await response.json(); | ||
expect(response.status).toEqual(200); | ||
expect(data).toMatchObject(queryMockResponse[query.getAccountHistory]); | ||
server.close(); | ||
}); | ||
|
||
it("rejects requests for non strings that are not pub keys", async () => { | ||
const notPubkey = "newp"; | ||
const server = await getDevServer(); | ||
const response = await fetch( | ||
`http://localhost:${ | ||
(server?.server?.address() as any).port | ||
}/api/v1/account-history/${notPubkey}` | ||
); | ||
expect(response.status).toEqual(400); | ||
server.close(); | ||
}); | ||
}); | ||
|
||
describe("/account-balances/:pubKey", () => { | ||
it("can fetch account balances for a pub key & contract IDs", async () => { | ||
const server = await getDevServer(); | ||
const response = await fetch( | ||
`http://localhost:${ | ||
(server?.server?.address() as any).port | ||
}/api/v1/account-balances/${pubKey}?contract_ids=CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP` | ||
); | ||
const { data } = await response.json(); | ||
expect(response.status).toEqual(200); | ||
expect(data.edges).toEqual( | ||
queryMockResponse["query.getAccountBalances"].edges | ||
); | ||
server.close(); | ||
}); | ||
|
||
it("can fetch account balances for a pub key & multiple contract IDs", async () => { | ||
const params = { | ||
contract_ids: [ | ||
"CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP", | ||
"CBGTG7XFRY3L6OKAUTR6KGDKUXUQBX3YDJ3QFDYTGVMOM7VV4O7NCODG", | ||
], | ||
}; | ||
const server = await getDevServer(); | ||
const response = await fetch( | ||
`http://localhost:${ | ||
(server?.server?.address() as any).port | ||
}/api/v1/account-balances/${pubKey}?${new URLSearchParams( | ||
params as any | ||
)}` | ||
); | ||
const { data } = await response.json(); | ||
expect(response.status).toEqual(200); | ||
expect(data.edges).toEqual( | ||
queryMockResponse["query.getAccountBalances"].edges | ||
); | ||
server.close(); | ||
}); | ||
|
||
it("rejects if any contract ID is not valid", async () => { | ||
const params = { | ||
contract_ids: [ | ||
"CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP", | ||
"newp", | ||
], | ||
}; | ||
const server = await getDevServer(); | ||
const response = await fetch( | ||
`http://localhost:${ | ||
(server?.server?.address() as any).port | ||
}/api/v1/account-balances/${pubKey}?${new URLSearchParams( | ||
params as any | ||
)}` | ||
); | ||
expect(response.status).toEqual(400); | ||
server.close(); | ||
}); | ||
|
||
it("rejects requests for non strings that are not pub keys", async () => { | ||
const notPubkey = "newp"; | ||
const server = await getDevServer(); | ||
const response = await fetch( | ||
`http://localhost:${ | ||
(server?.server?.address() as any).port | ||
}/api/v1/account-balances/${notPubkey}?contract_ids=CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP` | ||
); | ||
expect(response.status).toEqual(400); | ||
server.close(); | ||
}); | ||
|
||
it("rejects requests with bad contract IDs query param", async () => { | ||
const notContractId = "newp"; | ||
const server = await getDevServer(); | ||
const response = await fetch( | ||
`http://localhost:${ | ||
(server?.server?.address() as any).port | ||
}/api/v1/account-balances/${pubKey}?contract_ids=${notContractId}` | ||
); | ||
expect(response.status).toEqual(400); | ||
server.close(); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.