fastify#FastifyInstance TypeScript Examples
The following examples show how to use
fastify#FastifyInstance.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: test-utils.ts From cardano-rosetta with Apache License 2.0 | 7 votes |
setupServer = (database: Pool, disableSearchApi = false): FastifyInstance => {
// let repositories;
const repositories = Repositories.configure(database);
const services = Services.configure(
repositories,
NETWORK_ID,
// eslint-disable-next-line no-magic-numbers
1097911063,
JSON.parse(fs.readFileSync(path.resolve(process.env.TOPOLOGY_FILE_PATH)).toString()),
Number(process.env.DEFAULT_RELATIVE_TTL)
);
return buildServer(services, cardanoCliMock, cardanoNodeMock, process.env.LOGGER_LEVEL, {
networkId: NETWORK_ID,
pageSize: Number(process.env.PAGE_SIZE) || DEFAULT_PAGE_SIZE,
mock: true,
disableSearchApi
});
}
Example #2
Source File: utils.ts From fastify-sse-v2 with MIT License | 7 votes |
export async function getFastifyServer(source: AsyncIterable<EventMessage>): Promise<FastifyInstance> {
const server = fastify();
server.register(FastifySSEPlugin);
server.get("/", function (req, res) {
res.header("x-test-header2", "test2");
res.sse(source);
});
await server.ready();
await new Promise<void>((resolve, reject) => {
server.listen(0, "127.0.0.1", (err) => {
if(err) {
return reject(err);
}
resolve();
});
});
return server;
}
Example #3
Source File: getBucket.ts From storage-api with Apache License 2.0 | 6 votes |
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default async function routes(fastify: FastifyInstance) {
const summary = 'Get details of a bucket'
const schema = createDefaultSchema(successResponseSchema, {
params: getBucketParamsSchema,
summary,
tags: ['bucket'],
})
fastify.get<getBucketRequestInterface>(
'/:bucketId',
{
schema,
},
async (request, response) => {
const { bucketId } = request.params
const {
data: results,
error,
status,
} = await request.postgrest
.from<Bucket>('buckets')
.select('id, name, owner, public, created_at, updated_at')
.eq('id', bucketId)
.single()
if (error) {
request.log.error({ error, bucketId }, 'failed to retrieve bucket info')
return response.status(400).send(transformPostgrestError(error, status))
}
request.log.info({ results }, 'results')
response.send(results)
}
)
}
Example #4
Source File: netowork-status-api.test.ts From cardano-rosetta with Apache License 2.0 | 6 votes |
describe('/network/status endpoint', () => {
let database: Pool;
let server: FastifyInstance;
beforeAll(async () => {
database = setupDatabase();
server = setupServer(database);
});
afterAll(async () => {
await database.end();
});
// eslint-disable-next-line max-len
test('If requested with valid payload, it should properly return an object containing proper status information', async () => {
const response = await server.inject({
method: 'post',
url: NETWORK_STATUS_ENDPOINT,
payload: generateNetworkPayload(CARDANO, MAINNET)
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json().genesis_block_identifier).toEqual(genesis_block_identifier);
expect(response.json().current_block_identifier).toEqual(latestBlockIdentifier);
expect(response.json().peers).toEqual(peers);
});
testInvalidNetworkParameters(
NETWORK_STATUS_ENDPOINT,
(blockchain, network) => generateNetworkPayload(blockchain, network),
() => server
);
});
Example #5
Source File: ipLocate.ts From iplocate with MIT License | 6 votes |
ipLocate = async (fastify: FastifyInstance) => {
fastify.get<SearchRequest>("/search", opts, (request, reply) => {
const { ip } = request.query;
const reader = getReader();
const cityInfo = reader.city(ip);
reply.send(cityInfo);
});
fastify.get("/health", {}, (_, reply) => {
const reader = getReader();
const cityInfo = reader.city("8.8.8.8");
const country = emptyToPartial<CountryRecord>(cityInfo.country);
reply.status(country ? 200 : 500);
reply.send();
});
}
Example #6
Source File: outputSchema.ts From mercurius-typescript with MIT License | 6 votes |
export async function writeOutputSchema(
app: FastifyInstance,
config: string | boolean
) {
if (!config) return
let targetPath: string
if (typeof config === 'boolean') {
targetPath = resolve('./schema.gql')
} else {
targetPath = resolve(config)
}
const { printSchemaWithDirectives } = await import('@graphql-tools/utils')
const schema = await formatPrettier(
printSchemaWithDirectives(app.graphql.schema),
'graphql'
)
await writeFileIfChanged(targetPath, schema)
}
Example #7
Source File: getAllBuckets.ts From storage-api with Apache License 2.0 | 6 votes |
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default async function routes(fastify: FastifyInstance) {
const summary = 'Gets all buckets'
const schema = createDefaultSchema(successResponseSchema, {
summary,
tags: ['bucket'],
})
fastify.get<AuthenticatedRequest>(
'/',
{
schema,
},
async (request, response) => {
// get list of all buckets
const {
data: results,
error,
status,
} = await request.postgrest
.from<Bucket>('buckets')
.select('id, name, public, owner, created_at, updated_at')
if (error) {
request.log.error({ error }, 'error bucket')
return response.status(400).send(transformPostgrestError(error, status))
}
request.log.info({ results }, 'results')
response.send(results)
}
)
}
Example #8
Source File: app.ts From one-platform with MIT License | 6 votes |
fastifyAppClosePlugin = (app: FastifyInstance): ApolloServerPlugin => {
return {
async serverWillStart() {
return {
async drainServer() {
await app.close();
},
};
},
};
}
Example #9
Source File: index.ts From storage-api with Apache License 2.0 | 6 votes |
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default async function routes(fastify: FastifyInstance) {
fastify.register(jwt)
fastify.register(postgrest)
fastify.register(createBucket)
fastify.register(emptyBucket)
fastify.register(getAllBuckets)
fastify.register(getBucket)
fastify.register(updateBucket)
fastify.register(async (fastify) => {
fastify.register(superUserPostgrest)
fastify.register(deleteBucket)
})
}
Example #10
Source File: index.ts From fastify-now with MIT License | 6 votes |
function addRequestHandler(
module: { [key in HTTPMethod]: NowRequestHandler },
method: HTTPMethod,
server: FastifyInstance,
fileRouteServerPath: string,
) {
const handler = module[method.toUpperCase()] as NowRequestHandler;
if (handler) {
server.log.debug(`${method.toUpperCase()} ${fileRouteServerPath}`);
server[method](fileRouteServerPath, handler.opts || {}, handler);
}
}
Example #11
Source File: app.ts From one-platform with MIT License | 6 votes |
function fastifyAppClosePlugin(app: FastifyInstance): ApolloServerPlugin {
return {
async serverWillStart() {
return {
async drainServer() {
await app.close();
},
};
},
};
}
Example #12
Source File: utils.ts From fastify-sse-v2 with MIT License | 6 votes |
export function getBaseUrl(fastifyInstance: FastifyInstance): string {
const address = fastifyInstance.server.address() as AddressInfo;
return `http://${address.address}:${address.port}`;
}
Example #13
Source File: graphql.spec.ts From nestjs-mercurius with MIT License | 6 votes |
graphqlSuite.before.each(async (ctx) => {
const module = await Test.createTestingModule({
imports: [ApplicationModule],
}).compile();
const app = module.createNestApplication<NestFastifyApplication>(
new FastifyAdapter(),
);
await app.init();
const fastify: FastifyInstance = app.getHttpAdapter().getInstance();
await fastify.ready();
ctx.app = app;
});
Example #14
Source File: deleteObject.ts From storage-api with Apache License 2.0 | 5 votes |
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default async function routes(fastify: FastifyInstance) {
const summary = 'Delete an object'
const schema = createDefaultSchema(successResponseSchema, {
params: deleteObjectParamsSchema,
summary,
tags: ['object'],
})
fastify.delete<deleteObjectRequestInterface>(
'/:bucketName/*',
{
schema,
},
async (request, response) => {
const { bucketName } = request.params
const objectName = request.params['*']
if (!isValidKey(objectName) || !isValidKey(bucketName)) {
return response
.status(400)
.send(createResponse('The key contains invalid characters', '400', 'Invalid key'))
}
const objectResponse = await request.postgrest
.from<Obj>('objects')
.delete()
.match({
name: objectName,
bucket_id: bucketName,
})
.single()
if (objectResponse.error) {
const { error, status } = objectResponse
request.log.error({ error }, 'error object')
return response.status(400).send(transformPostgrestError(error, status))
}
const { data: results } = objectResponse
request.log.info({ results }, 'results')
// if successfully deleted, delete from s3 too
const s3Key = `${request.tenantId}/${bucketName}/${objectName}`
await storageBackend.deleteObject(globalS3Bucket, s3Key)
return response.status(200).send(createResponse('Successfully deleted'))
}
)
}
Example #15
Source File: base-mercurius.module.ts From nestjs-mercurius with MIT License | 5 votes |
protected async registerFastify(mercuriusOptions: Opts) {
const mercurius = loadPackage('mercurius', 'MercuriusModule', () =>
require('mercurius'),
);
const httpAdapter = this.httpAdapterHost.httpAdapter;
const app: FastifyInstance = httpAdapter.getInstance();
const options = {
...mercuriusOptions,
path: this.getNormalizedPath(mercuriusOptions),
};
if (mercuriusOptions.uploads) {
const mercuriusUpload = loadPackage(
'mercurius-upload',
'MercuriusModule',
() => require('mercurius-upload'),
);
await app.register(
mercuriusUpload,
typeof mercuriusOptions.uploads !== 'boolean'
? mercuriusOptions.uploads
: undefined,
);
}
if (mercuriusOptions.altair) {
const altairPlugin = loadPackage(
'altair-fastify-plugin',
'MercuriusModule',
() => require('altair-fastify-plugin'),
);
options.graphiql = false;
options.ide = false;
await app.register(altairPlugin, {
baseURL: '/altair/',
path: '/altair',
...(typeof mercuriusOptions.altair !== 'boolean' &&
mercuriusOptions.altair),
endpointURL: options.path,
});
}
await app.register(mercurius, options);
this.addHooks(app);
}
Example #16
Source File: admin-app.ts From storage-api with Apache License 2.0 | 5 votes |
build = (opts: FastifyServerOptions = {}): FastifyInstance => {
const app = fastify(opts)
app.register(tenantRoutes, { prefix: 'tenants' })
app.register(underPressure, { exposeStatusRoute: true, maxEventLoopUtilization: 0.99 })
return app
}
Example #17
Source File: base-mercurius.module.ts From nestjs-mercurius with MIT License | 5 votes |
protected addHooks(app: FastifyInstance) {
const hooks = this.hookExplorerService.explore();
hooks.forEach((hook) => {
app.graphql.addHook(hook.name as any, hook.callback as any);
});
}
Example #18
Source File: node.ts From hubble-contracts with MIT License | 5 votes |
public static async init(config: ClientConfig, fast: FastifyInstance) {
await mcl.init();
const genesis = await Genesis.fromConfig(config.genesisPath);
const provider = new ethers.providers.JsonRpcProvider(
config.providerUrl,
genesis.auxiliary.chainid
);
provider.on("error", err => {
console.error(err);
});
const { MAX_DEPTH } = genesis.parameters;
const storageManager = await storageManagerFactory({
stateTreeDepth: MAX_DEPTH,
pubkeyTreeDepth: MAX_DEPTH
});
const signer = provider.getSigner();
const api = CoreAPI.new(storageManager, genesis, provider, signer);
const syncer = new SyncerService(api);
let transferPool;
let packer;
let bidder;
const modes = this.getNodeModes(config);
if (modes.isProposer) {
const { feeReceivers, willingnessToBid, maxPendingTransactions } =
config.proposer || {};
if (!feeReceivers) {
throw new MissingConfigPropError("proposer.feeRecievers");
}
if (!feeReceivers.length) {
throw new EmptyConfigPropError("proposer.feeRecievers");
}
if (!willingnessToBid) {
throw new MissingConfigPropError("proposer.willingnessToBid");
}
transferPool = new TransferPool(
storageManager.state,
feeReceivers,
maxPendingTransactions
);
packer = new Packer(api, transferPool);
bidder = await Bidder.new(
BigNumber.from(willingnessToBid),
api.contracts.burnAuction
);
}
if (modes.isWatcher) {
throw new Error("watcher is currently not supported");
}
fast.addHook("onRequest", async (_request, reply) => {
if (syncer.getMode() === SyncMode.INITIAL_SYNCING) {
return reply.status(503).send({
message: "Initial sync incomplete",
error: "RPC unavailable",
statusCode: 503
});
}
});
const rpc = new RPC(api, fast, transferPool);
return new this(
modes,
provider,
api.eventEmitter,
syncer,
packer,
bidder,
rpc
);
}
Example #19
Source File: moveObject.ts From storage-api with Apache License 2.0 | 5 votes |
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default async function routes(fastify: FastifyInstance) {
const summary = 'Moves an object'
const schema = createDefaultSchema(successResponseSchema, {
body: moveObjectsBodySchema,
summary,
tags: ['object'],
})
fastify.post<moveObjectRequestInterface>(
'/move',
{
schema,
},
async (request, response) => {
const { destinationKey, sourceKey, bucketId } = request.body
if (!isValidKey(destinationKey)) {
return response
.status(400)
.send(
createResponse('The destination key contains invalid characters', '400', 'Invalid key')
)
}
const objectResponse = await request.postgrest
.from<Obj>('objects')
.update({
last_accessed_at: new Date().toISOString(),
name: destinationKey,
})
.match({ bucket_id: bucketId, name: sourceKey })
.single()
if (objectResponse.error) {
const { status, error } = objectResponse
request.log.error({ error }, 'error object')
return response.status(400).send(transformPostgrestError(error, status))
}
// if successfully updated, copy and delete object from s3
const oldS3Key = `${request.tenantId}/${bucketId}/${sourceKey}`
const newS3Key = `${request.tenantId}/${bucketId}/${destinationKey}`
// @todo what happens if one of these fail?
await storageBackend.copyObject(globalS3Bucket, oldS3Key, newS3Key)
await storageBackend.deleteObject(globalS3Bucket, oldS3Key)
return response.status(200).send(createResponse('Successfully moved'))
}
)
}
Example #20
Source File: pub-sub-host.ts From nestjs-mercurius with MIT License | 5 votes |
getInstance(): PubSub | undefined {
return this.httpAdapterHost.httpAdapter.getInstance<FastifyInstance>()
.graphql?.pubsub;
}
Example #21
Source File: getPublicObject.ts From storage-api with Apache License 2.0 | 5 votes |
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default async function routes(fastify: FastifyInstance) {
const summary = 'Retrieve an object from a public bucket'
fastify.get<getObjectRequestInterface>(
'/public/:bucketName/*',
{
// @todo add success response schema here
schema: {
params: getPublicObjectParamsSchema,
summary,
response: { '4xx': { $ref: 'errorSchema#' } },
tags: ['object'],
},
},
async (request, response) => {
const { bucketName } = request.params
const objectName = request.params['*']
const { error, status } = await request.superUserPostgrest
.from<Bucket>('buckets')
.select('id, public')
.eq('id', bucketName)
.eq('public', true)
.single()
if (error) {
request.log.error({ error }, 'error finding public bucket')
return response.status(400).send(transformPostgrestError(error, status))
}
const s3Key = `${request.tenantId}/${bucketName}/${objectName}`
request.log.info(s3Key)
try {
const data = await storageBackend.getObject(globalS3Bucket, s3Key, {
ifModifiedSince: request.headers['if-modified-since'],
ifNoneMatch: request.headers['if-none-match'],
range: request.headers.range,
})
response
.status(data.metadata.httpStatusCode ?? 200)
.header('Accept-Ranges', 'bytes')
.header('Content-Type', normalizeContentType(data.metadata.mimetype))
.header('Cache-Control', data.metadata.cacheControl)
.header('Content-Length', data.metadata.contentLength)
.header('ETag', data.metadata.eTag)
.header('Last-Modified', data.metadata.lastModified)
if (data.metadata.contentRange) {
response.header('Content-Range', data.metadata.contentRange)
}
return response.send(data.body)
} catch (err: any) {
if (err.$metadata?.httpStatusCode === 304) {
return response.status(304).send()
}
request.log.error(err)
if (err.$metadata?.httpStatusCode === 404) {
return response.status(404).send()
} else {
return response.status(400).send({
message: err.message,
statusCode: '400',
error: err.message,
})
}
}
}
)
}
Example #22
Source File: code-first.spec.ts From nestjs-mercurius with MIT License | 5 votes |
gqlSuite('subscriber should work', async ({ app }) => {
return new Promise<void>((resolve, reject) => {
app.listen(0, (err) => {
if (err) {
return reject(err);
}
const port = app.getHttpServer().address().port;
const fastifyApp = app.getHttpAdapter().getInstance() as FastifyInstance;
const ws = new Websocket(`ws://localhost:${port}/graphql`, 'graphql-ws');
const client = Websocket.createWebSocketStream(ws, {
encoding: 'utf8',
objectMode: true,
});
client.setEncoding('utf8');
client.write(
JSON.stringify({
type: 'connection_init',
}),
);
client.write(
JSON.stringify({
id: 1,
type: 'start',
payload: {
query: `
subscription {
onCatSub {
id
lives
name
hasFur
}
}
`,
},
}),
);
client.on('data', (chunk) => {
const data = JSON.parse(chunk);
if (data.type === 'connection_ack') {
fastifyApp.graphql.pubsub.publish({
topic: 'CAT_SUB_TOPIC',
payload: cats[0],
});
} else if (data.id === 1) {
const expectedCat = expectedCats[0];
const receivedCat = data.payload.data?.onCatSub;
assert.ok(receivedCat);
assert.equal(expectedCat.id, receivedCat.id);
assert.type(receivedCat.hasFur, 'boolean');
client.end();
}
});
client.on('end', () => {
client.destroy();
app.close().then(resolve).catch(reject);
});
});
});
});
Example #23
Source File: listObjects.ts From storage-api with Apache License 2.0 | 5 votes |
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default async function routes(fastify: FastifyInstance) {
const summary = 'Search for objects under a prefix'
const schema = createDefaultSchema(successResponseSchema, {
body: searchRequestBodySchema,
params: searchRequestParamsSchema,
summary,
tags: ['object'],
})
fastify.post<searchRequestInterface>(
'/list/:bucketName',
{
schema,
},
async (request, response) => {
const { bucketName } = request.params
const { limit, offset, sortBy, search } = request.body
let sortColumn, sortOrder
if (sortBy?.column) {
sortColumn = sortBy.column
sortOrder = sortBy.order ?? 'asc'
} else {
sortColumn = 'name'
sortOrder = 'asc'
}
let { prefix } = request.body
if (prefix.length > 0 && !prefix.endsWith('/')) {
// assuming prefix is always a folder
prefix = `${prefix}/`
}
request.log.info(request.body)
request.log.info(`searching for %s`, prefix)
const {
data: results,
error,
status,
} = await request.postgrest.rpc('search', {
prefix,
bucketname: bucketName,
limits: limit,
offsets: offset,
levels: prefix.split('/').length,
search,
sortcolumn: sortColumn,
sortorder: sortOrder,
})
if (error) {
request.log.error({ error }, 'search rpc')
return response.status(status).send(transformPostgrestError(error, status))
}
request.log.info({ results }, 'results')
response.status(200).send(results)
}
)
}
Example #24
Source File: router.ts From iplocate with MIT License | 5 votes |
export default async function router(fastify: FastifyInstance) {
fastify.register(ipLocate, { prefix: "/ip" });
}
Example #25
Source File: construction-metadata-api.test.ts From cardano-rosetta with Apache License 2.0 | 5 votes |
describe(CONSTRUCTION_METADATA_ENDPOINT, () => {
let database: Pool;
let server: FastifyInstance;
beforeAll(async () => {
database = setupOfflineDatabase();
server = setupServer(database);
});
afterAll(async () => {
await database.end();
});
beforeAll(async () => {
database = setupDatabase();
server = setupServer(database);
});
test('Should return a valid TTL when the parameters are valid', async () => {
const relativeTtl = 100;
const response = await server.inject({
method: 'post',
url: CONSTRUCTION_METADATA_ENDPOINT,
payload: generateMetadataPayload('cardano', 'mainnet', relativeTtl)
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual({
metadata: {
ttl: (latestBlockSlot + relativeTtl).toString()
},
suggested_fee: [
{
currency: {
decimals: 6,
symbol: 'ADA'
},
// ttl is encoded as 5 bytes but metadata comes with one already
value: (
(TRANSACTION_SIZE_IN_BYTES + 4) * linearFeeParameters.minFeeA +
linearFeeParameters.minFeeB
).toString()
}
]
});
});
testInvalidNetworkParameters(
CONSTRUCTION_METADATA_ENDPOINT,
(blockchain, network) => generateMetadataPayload(blockchain, network, 100),
() => server
);
});
Example #26
Source File: http.ts From walletconnect-v2-monorepo with Apache License 2.0 | 5 votes |
public app: FastifyInstance;
Example #27
Source File: block-transactions-api.test.ts From cardano-rosetta with Apache License 2.0 | 4 votes |
describe('/block/transactions endpoint', () => {
let database: Pool;
let server: FastifyInstance;
beforeAll(async () => {
database = setupDatabase();
server = setupServer(database);
});
afterAll(async () => {
await database.end();
});
const BLOCK_TRANSACTION_ENDPOINT = '/block/transaction';
test('should return the transaction if a valid hash is sent', async () => {
const { index, hash } = block23236WithTransactions.block.block_identifier;
const [transaction] = block23236WithTransactions.block.transactions;
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(index, hash),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction.transaction_identifier.hash
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual({ transaction });
});
test('should return an error if the transaction doesnt exist', async () => {
const { index, hash } = block23236WithTransactions.block.block_identifier;
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(index, hash),
// eslint-disable-next-line camelcase
transaction_identifier: {
// Last digit was changed from 4 to 5
hash: 'abbeb108ebc3990c7f031113bcb8ce8f306a1eec8f313acffcdcd256379208f5'
}
}
});
expect(response.statusCode).toEqual(StatusCodes.INTERNAL_SERVER_ERROR);
expect(response.json()).toEqual({ code: 4006, message: TRANSACTION_NOT_FOUND, retriable: false });
});
test('should fail if incorrect network identifier is sent', async () => {
const { index, hash } = block23236WithTransactions.block.block_identifier;
const [transaction] = block23236WithTransactions.block.transactions;
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(index, hash),
// eslint-disable-next-line camelcase
network_identifier: {
blockchain: 'cardano',
network: 'testnet'
},
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction.transaction_identifier.hash
}
}
});
expect(response.statusCode).toEqual(StatusCodes.INTERNAL_SERVER_ERROR);
expect(response.json()).toEqual({ message: 'Network not found', code: 4002, retriable: false });
});
test('should fail if incorrect blockchain identifier is sent', async () => {
const { index, hash } = block23236WithTransactions.block.block_identifier;
const [transaction] = block23236WithTransactions.block.transactions;
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(index, hash),
// eslint-disable-next-line camelcase
network_identifier: {
blockchain: 'incorrect',
network: 'mainnet'
},
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction.transaction_identifier.hash
}
}
});
expect(response.statusCode).toEqual(StatusCodes.INTERNAL_SERVER_ERROR);
expect(response.json()).toEqual({ message: 'Invalid blockchain', code: 4004, retriable: false });
});
test('should fail if requested block index does not correspond to requested block hash', async () => {
const { hash } = block23236WithTransactions.block.block_identifier;
const [transaction] = block23236WithTransactions.block.transactions;
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(1234, hash),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction.transaction_identifier.hash
}
}
});
expect(response.statusCode).toEqual(StatusCodes.INTERNAL_SERVER_ERROR);
expect(response.json()).toEqual({ message: TRANSACTION_NOT_FOUND, code: 4006, retriable: false });
});
test('should fail if requested block hash does not correspond to requested block index', async () => {
const { index } = block23236WithTransactions.block.block_identifier;
const [transaction] = block23236WithTransactions.block.transactions;
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(index, 'fakeHash'),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction.transaction_identifier.hash
}
}
});
expect(response.statusCode).toEqual(StatusCodes.INTERNAL_SERVER_ERROR);
expect(response.json()).toEqual({ message: TRANSACTION_NOT_FOUND, code: 4006, retriable: false });
});
test('should return transaction for genesis block when requested', async () => {
const genesisIndex = 0;
const genesisHash = '5f20df933584822601f9e3f8c024eb5eb252fe8cefb24d1317dc3d432e940ebb';
const transaction = '927edb96f3386ab91b5f5d85d84cb4253c65b1c2f65fa7df25f81fab1d62987a';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(genesisIndex, genesisHash),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual(transaction987aOnGenesis);
});
test('should return transaction withdrawals', async () => {
const transaction = '2974845ecc7e02e86285d32961c69f3945662a80d5e2caae8a1086e652936f42';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(4597861, 'e73be90cd5e2b0bf3acb86e3bed575931ab0ff1e7d5bfca94cff6166ef010060'),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual(transactionBlock4597861WithWithdrawals);
});
test('should return transaction registrations', async () => {
const transaction = '91f88c21679fdc95cb0712dc8a755eab20fdf9e919871c3c668515c830572090';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(4490558, '600fc0fc8b9d4bcb777536cd9168703d0645ab4986fe8d3bdae4011ad0ee5919'),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual(transactionBlock4490558WithRegistrations);
});
test('should return transaction delegations', async () => {
const transaction = 'f0024159d124a128db522031c4a3e7b255ee511600afa92ff52b2504702e4e1d';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(4490559, 'd5c4088f55024cb5a087c1588ff362d6c5c1a95ada0608044192c320b41c5987'),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual(transactionBlock4490559WithDelegation);
});
test('should return transaction deregistrations', async () => {
const transaction = '5fe53eece38ff4eb102c33c6cbdf34947c8232eefaae0731fdf8f746b81763fc';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(4853177, '6713e3dbea2a037f0be9401744a8b2be4c6190294a23c496165c212972a82f61'),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual(transactionBlock4853177WithDeregistration);
});
test('should return a pool retirement transaction', async () => {
const transaction = '896cf8fefad1eaf0fa056ba3adf28bfb26b06d1beed64cf790deb595dcb2687a';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(4491210, 'ddb008b4a1cad00db90f524b5ba94da94f84b2aabe7de6ff4a0d27d89ed222dd'),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual(transactionBlock4853177WithPoolRetirement);
});
test('should be able to return multiasset token transactions with several tokens in the bundle', async () => {
const transaction = '8d67291066037f46f092bfc098241cc7143fa1ec2b14b6c23b945878ccf9fe0f';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(5407534, '6d48a3e7af71698268ea3efaf67a2f012e237b19e10131eb77cd22448fd4183c'),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual({ transaction: transaction5407534WithTokenBundle });
});
test('should return transaction pool registrations', async () => {
const transaction = '29a76dd58c6309cd9cde855c0c50d81d63f921959359b1e544401ac1dbc9b472';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(4597779, '8839b697618eb1b3167bcd2658e10008d9c1d11bd32b305abf497371cd79dafa'),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual(transactionWithPoolRegistration);
});
test('should return transaction pool registrations with multiple owners', async () => {
const transaction = '51d67e194d749df2abf4e2e11cea63ca6e1c630042a366f555939e795a6ddecf';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(4490593, 'a5f1a0e14e1ca218fd07e1601792545945c8cb552d7978967e230d6d3b2710fd'),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: transaction
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual(transactionWithPoolRegistrationWithMultipleOwners);
});
// TODO: deprecated. pending to be implemented
// test('should return operation status as invalid when there is an invalid transaction', async () => {
// const invalidTxHash = '0c2d516c9eaf0d9f641506f1f64be3f660a49e622f4651ed1b19d6edeaefaf4c';
// const blockNumber = 25050;
// const blockHash = '1f58250b82bc7c7c408028ba01173bdfa37fc82dde34060c5b49a3ea644d9439';
// const response = await serverWithAlonzoSupport.inject({
// method: 'post',
// url: BLOCK_TRANSACTION_ENDPOINT,
// payload: {
// ...generatePayload(blockNumber, blockHash),
// // eslint-disable-next-line camelcase
// transaction_identifier: {
// hash: invalidTxHash
// }
// }
// });
// expect(response.statusCode).toEqual(StatusCodes.OK);
// expect(response.json()).toEqual(invalidAlonzoTransaction);
// });
test('should return vote registration operations', async () => {
const txHash = 'adeb7b6845f3f4b0e74275588412cf00912b615e4bbf76d111326ce899260c59';
const blockNumber = 5593749;
const blockHash = '1c42fd317888b2aafe9f84787fdd3b90b95be06687a217cf4e6ca95130157eb5';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(blockNumber, blockHash),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: txHash
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual(transactionWithVoteOperation);
});
test('should not return a vote registration operation when it is bad formed', async () => {
const txHash = 'cacbc12afa3a1d2ec0186971d5c9035c79bfa1250ca7a6af580d1b8d9e04db8c';
const blockNumber = 5406810;
const blockHash = '0cea06f7b3003a5c0efc27fff117fa9e2a08603e1b0049c3b5c719abf6a617f1';
const response = await server.inject({
method: 'post',
url: BLOCK_TRANSACTION_ENDPOINT,
payload: {
...generatePayload(blockNumber, blockHash),
// eslint-disable-next-line camelcase
transaction_identifier: {
hash: txHash
}
}
});
expect(response.statusCode).toEqual(StatusCodes.OK);
expect(response.json()).toEqual(transactionWithBadFormedVote);
});
});
Example #28
Source File: rpc.ts From hubble-contracts with MIT License | 4 votes |
constructor(
{ l2Storage }: CoreAPI,
fastify: FastifyInstance,
transferPool?: ITransferPool
) {
fastify.register(cors, {
origin: "*"
});
fastify.get<{ Params: { stateID: number } }>(
"/user/state/:stateID",
async function(request, reply) {
try {
const { stateID } = request.params;
const state = await l2Storage.state.get(stateID);
return state.toJSON();
} catch (error) {
if (error.name === "NotFoundError") {
return reply
.status(404)
.send({ error: "pubkey not found" });
} else {
console.error(error);
return reply.status(500);
}
}
}
);
fastify.get<{ Params: { pubkeyHash: string } }>(
"/user/state/pubkey/:pubkeyHash",
async function(request, reply) {
try {
const { pubkeyHash } = request.params;
const stateIndices = await Pubkey2StatesDB.getStates(
pubkeyHash
);
let data = stateIndices.map(async id => {
let state = await l2Storage.state.get(Number(id));
return {
stateId: id,
balance: state.balance.toString(),
tokenId: state.tokenID.toString(),
nonce: state.nonce.toString()
};
});
return { states: await Promise.all(data) };
} catch (error) {
if (error.name === "NotFoundError") {
return reply
.status(404)
.send({ error: "pubkey not found" });
} else {
console.error(error);
return reply.status(500);
}
}
}
);
fastify.get<{ Params: { pubkeyID: number } }>(
"/user/pubkey/hash/:pubkeyID",
async function(request, reply) {
try {
const { pubkeyID } = request.params;
const pubkey = await l2Storage.pubkey.get(pubkeyID);
return { hash: pubkey.hash() };
} catch (error) {
return reply
.status(404)
.send({ error: "pubkey not found" });
}
}
);
fastify.get<{ Params: { pubkeyHash: string } }>(
"/user/pubkey/id/:pubkeyHash",
async function(request, reply) {
try {
const { pubkeyHash } = request.params;
const stateIndices = await Pubkey2StatesDB.getStates(
pubkeyHash
);
let data = await l2Storage.state.get(
Number(stateIndices[0])
);
return { id: data.pubkeyID.toNumber() };
} catch (error) {
if (error.name === "NotFoundError") {
return reply
.status(404)
.send({ error: "pubkey not found" });
} else {
console.error(error);
return reply.status(500);
}
}
}
);
fastify.post<{ Body: { bytes: string } }>(
"/tx",
tx,
async (request, reply) => {
try {
if (!transferPool) {
reply.status(409).send("not a proposer");
return;
}
const bytes = arrayify(request.body.bytes);
const transfer = TransferOffchainTx.deserialize(bytes);
await transferPool.push(transfer);
await l2Storage.transactions.pending(transfer);
return { txHash: transfer.hash() };
} catch (error) {
console.error(error);
return reply.status(500);
}
}
);
fastify.get<{ Params: { txMsg: string } }>(
"/tx/:txMsg",
async (request, reply) => {
const { txMsg } = request.params;
const txStatus = await l2Storage.transactions.get(txMsg);
if (!txStatus) {
reply.status(404).send(`${txMsg} not found`);
return;
}
// In the future, we may want to clean up
// this JSON serialization to something more minimal.
return JSON.stringify({
status: txStatus.status,
l1BlockIncluded: txStatus.l1BlockIncluded,
l1TxnHash: txStatus.l1TxnHash
});
}
);
}
Example #29
Source File: index.ts From mercurius-typescript with MIT License | 4 votes |
export async function codegenMercurius(
app: FastifyInstance,
{
disable = process.env.NODE_ENV === 'production',
targetPath,
silent,
codegenConfig,
preImportCode,
operationsGlob,
watchOptions,
outputSchema = false,
}: CodegenMercuriusOptions
): Promise<{
closeWatcher: () => Promise<boolean>
watcher: Promise<FSWatcher | undefined>
}> {
const noopCloseWatcher = async () => false
if (disable) {
return {
closeWatcher: noopCloseWatcher,
watcher: Promise.resolve(undefined),
}
}
await app.ready()
if (typeof app.graphql !== 'function') {
throw Error('Mercurius is not registered in Fastify Instance!')
}
const { generateCode, writeGeneratedCode } = await import('./code')
const { writeOutputSchema } = await import('./outputSchema')
return new Promise((resolve, reject) => {
const log = (...message: Parameters<typeof console['log']>) =>
silent ? undefined : console.log(...message)
setImmediate(() => {
const schema = app.graphql.schema
async function watchExecute() {
const {
enabled: watchEnabled = false,
chokidarOptions,
uniqueWatch = true,
} = watchOptions || {}
if (watchEnabled && operationsGlob) {
const { watch } = await import('chokidar')
let watcherPromise = deferredPromise<FSWatcher | undefined>()
const watcher = watch(
operationsGlob,
Object.assign(
{
useFsEvents: false,
} as ChokidarOptions,
chokidarOptions
)
)
let isReady = false
watcher.on('ready', () => {
isReady = true
log(`[mercurius-codegen] Watching for changes in ${operationsGlob}`)
watcherPromise.resolve(watcher)
})
watcher.on('error', watcherPromise.reject)
let closed = false
const closeWatcher = async () => {
if (closed) return false
closed = true
await watcher.close()
return true
}
if (uniqueWatch) {
if (typeof global.mercuriusOperationsWatchCleanup === 'function') {
global.mercuriusOperationsWatchCleanup()
}
global.mercuriusOperationsWatchCleanup = closeWatcher
}
const listener = (
eventName: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir',
changedPath: string
) => {
if (!isReady) return
log(
`[mercurius-codegen] ${changedPath} ${eventName}, re-generating...`
)
generateCode(
schema,
codegenConfig,
preImportCode,
silent,
operationsGlob
).then((code) => {
writeGeneratedCode({
code,
targetPath,
}).then((absoluteTargetPath) => {
log(
`[mercurius-codegen] Code re-generated at ${absoluteTargetPath}`
)
}, console.error)
}, console.error)
}
watcher.on('all', listener)
return {
closeWatcher,
watcher: watcherPromise.promise,
}
}
return {
closeWatcher: noopCloseWatcher,
watcher: Promise.resolve(undefined),
}
}
writeOutputSchema(app, outputSchema).catch(reject)
generateCode(
schema,
codegenConfig,
preImportCode,
silent,
operationsGlob
).then((code) => {
writeGeneratedCode({
code,
targetPath,
}).then((absoluteTargetPath) => {
log(`[mercurius-codegen] Code generated at ${absoluteTargetPath}`)
watchExecute().then((watchResult) => {
resolve(watchResult)
}, reject)
}, reject)
}, reject)
})
})
}