Skip to content

Commit

Permalink
add Blockaid reporting endpoints (#196)
Browse files Browse the repository at this point in the history
* add Blockaid reporting endpoints

* use Blockaid tx warning type and update tests
  • Loading branch information
piyalbasu authored Jan 7, 2025
1 parent 64efa2d commit 0817328
Show file tree
Hide file tree
Showing 8 changed files with 270 additions and 7 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"node": ">=18.12.0"
},
"dependencies": {
"@blockaid/client": "^0.32.0",
"@blockaid/client": "^0.34.0",
"@fastify/cors": "^10.0.1",
"@fastify/helmet": "^13.0.0",
"@fastify/rate-limit": "^10.2.1",
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ export function buildConfig(config: Record<string, string | undefined>) {
useBlockaidDappScanning: true,
useBlockaidTxScanning: true,
useBlockaidAssetScanning: true,
useBlockaidAssetWarningReporting: true,
useBlockaidTransactionWarningReporting: true,
},
};
}
Expand Down
4 changes: 4 additions & 0 deletions src/helper/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ export const ERROR = {
SCAN_SITE_DISABLED: "scanning site using blockaid is disabled",
SCAN_TX_DISABLED: "scanning tx using blockaid is disabled",
SCAN_ASSET_DISABLED: "scanning asset using blockaid is disabled",
REPORT_ASSET_DISABLED: "reporting asset is disabled",
UNABLE_TO_REPORT_ASSET: "unable to report asset to blockaid",
REPORT_TRANSACTION_DISABLED: "reporting transaction is disabled",
UNABLE_TO_REPORT_TRANSACTION: "unable to report transaction to blockaid",
};
2 changes: 2 additions & 0 deletions src/helper/test-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,8 @@ async function getDevServer(
useBlockaidAssetScanning: true,
useBlockaidDappScanning: true,
useBlockaidTxScanning: true,
useBlockaidAssetWarningReporting: true,
useBlockaidTransactionWarningReporting: true,
},
) {
const server = await initApiServer(
Expand Down
107 changes: 107 additions & 0 deletions src/route/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { query } from "../service/mercury/queries";
import { defaultBenignResponse } from "../service/blockaid/helpers/addScanResults";
import { Networks } from "stellar-sdk-next";
import { SOROBAN_RPC_URLS } from "../helper/soroban-rpc";
import { ERROR } from "../helper/error";
import * as StellarHelpers from "../helper/stellar";

jest.mock("@blockaid/client", () => {
Expand Down Expand Up @@ -64,6 +65,12 @@ jest.mock("@blockaid/client", () => {
malicious_score: 0,
});
},
report: () => Promise.resolve(999),
};
stellar = {
transaction: {
report: () => Promise.resolve(999),
},
};
};
});
Expand Down Expand Up @@ -320,6 +327,8 @@ describe("API routes", () => {
useBlockaidAssetScanning: false,
useBlockaidDappScanning: false,
useBlockaidTxScanning: false,
useBlockaidAssetWarningReporting: true,
useBlockaidTransactionWarningReporting: true,
});
const url = new URL(
`http://localhost:${
Expand Down Expand Up @@ -380,6 +389,8 @@ describe("API routes", () => {
useBlockaidAssetScanning: false,
useBlockaidDappScanning: false,
useBlockaidTxScanning: false,
useBlockaidAssetWarningReporting: true,
useBlockaidTransactionWarningReporting: true,
});
const url = new URL(
`http://localhost:${
Expand All @@ -403,6 +414,102 @@ describe("API routes", () => {
await server.close();
});
});
describe("/report-asset-warning", () => {
it("can report an asset warning", async () => {
const server = await getDevServer();
const url = new URL(
`http://localhost:${
(server?.server?.address() as any).port
}/api/v1/report-asset-warning`,
);
url.searchParams.append(
"address",
"BLND-GATALTGTWIOT6BUDBCZM3Q4OQ4BO2COLOAZ7IYSKPLC2PMSOPPGF5V56",
);
url.searchParams.append("details", "foo");
const response = await fetch(url.href);
const data = await response.json();

expect(response.status).toEqual(200);
expect(data.data).toEqual(999);
register.clear();
await server.close();
});
it("does not report an asset warning when config is disabled", async () => {
const server = await getDevServer({
useBlockaidAssetScanning: false,
useBlockaidDappScanning: false,
useBlockaidTxScanning: false,
useBlockaidAssetWarningReporting: false,
useBlockaidTransactionWarningReporting: true,
});
const url = new URL(
`http://localhost:${
(server?.server?.address() as any).port
}/api/v1/report-asset-warning`,
);
url.searchParams.append(
"address",
"BLND-GATALTGTWIOT6BUDBCZM3Q4OQ4BO2COLOAZ7IYSKPLC2PMSOPPGF5V56",
);
url.searchParams.append("details", "foo");
const response = await fetch(url.href);
const data = await response.json();

expect(response.status).toEqual(200);
expect(data).toEqual({
error: ERROR.REPORT_ASSET_DISABLED,
});
register.clear();
await server.close();
});
});
describe.only("/report-transaction-warning", () => {
it("can report a transaction warning", async () => {
const server = await getDevServer();
const url = new URL(
`http://localhost:${
(server?.server?.address() as any).port
}/api/v1/report-transaction-warning`,
);
url.searchParams.append("details", "foo");
url.searchParams.append("request_id", "baz");
url.searchParams.append("event", "should_be_malicious");
const response = await fetch(url.href);
const data = await response.json();

expect(response.status).toEqual(200);
expect(data.data).toEqual(999);
register.clear();
await server.close();
});
it("does not report an trandaction warning when config is disabled", async () => {
const server = await getDevServer({
useBlockaidAssetScanning: false,
useBlockaidDappScanning: false,
useBlockaidTxScanning: false,
useBlockaidAssetWarningReporting: true,
useBlockaidTransactionWarningReporting: false,
});
const url = new URL(
`http://localhost:${
(server?.server?.address() as any).port
}/api/v1/report-transaction-warning`,
);
url.searchParams.append("details", "foo");
url.searchParams.append("request_id", "baz");
url.searchParams.append("event", "should_be_malicious");
const response = await fetch(url.href);
const data = await response.json();

expect(response.status).toEqual(200);
expect(data).toEqual({
error: ERROR.REPORT_TRANSACTION_DISABLED,
});
register.clear();
await server.close();
});
});
describe("/simulate-tx", () => {
const simResponse = "simulated xdr";
const preparedTransaction = "assembled tx xdr";
Expand Down
99 changes: 99 additions & 0 deletions src/route/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { MercuryClient } from "../service/mercury";
import {
BlockAidService,
BlockaidAssetScanResponse,
ReportTransactionWarningEvent,
} from "../service/blockaid";
import {
addScannedStatus,
Expand Down Expand Up @@ -54,6 +55,8 @@ export async function initApiServer(
useBlockaidDappScanning: boolean;
useBlockaidTxScanning: boolean;
useBlockaidAssetScanning: boolean;
useBlockaidAssetWarningReporting: boolean;
useBlockaidTransactionWarningReporting: boolean;
},
redis?: Redis,
) {
Expand Down Expand Up @@ -771,6 +774,102 @@ export async function initApiServer(
},
});

instance.route({
method: "GET",
url: "/report-asset-warning",
schema: {
querystring: {
type: "object",
required: ["details", "address"],
properties: {
["details"]: {
type: "string",
},
["address"]: {
type: "string",
},
},
},
},
handler: async (
request: FastifyRequest<{
Querystring: {
["details"]: string;
["address"]: string;
};
}>,
reply,
) => {
const { details, address } = request.query;

if (blockaidConfig.useBlockaidAssetWarningReporting) {
try {
const { data, error } = await blockAidService.reportAssetWarning(
details,
address,
);
return reply.code(error ? 400 : 200).send({ data, error });
} catch (error) {
return reply.code(500).send({ error: ERROR.SERVER_ERROR });
}
}
return reply.code(200).send({
error: ERROR.REPORT_ASSET_DISABLED,
});
},
});

instance.route({
method: "GET",
url: "/report-transaction-warning",
schema: {
querystring: {
type: "object",
required: ["details", "request_id", "event"],
properties: {
["details"]: {
type: "string",
},
["request_id"]: {
type: "string",
},
["event"]: {
type: "string",
},
},
},
},
handler: async (
request: FastifyRequest<{
Querystring: {
["details"]: string;
["request_id"]: string;
["event"]: ReportTransactionWarningEvent;
};
}>,
reply,
) => {
const { details, request_id, event } = request.query;

if (blockaidConfig.useBlockaidTransactionWarningReporting) {
try {
const { data, error } =
await blockAidService.reportTransactionWarning(
details,
request_id,
event,
);
return reply.code(error ? 400 : 200).send({ data, error });
} catch (error) {
return reply.code(500).send({ error: ERROR.SERVER_ERROR });
}
}
return reply.code(200).send({
error: ERROR.REPORT_TRANSACTION_DISABLED,
});
},
});

instance.route({
method: "POST",
url: "/subscription/token",
Expand Down
53 changes: 51 additions & 2 deletions src/service/blockaid/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ const NetworkNameBlockaid: {

export type BlockaidAssetScanResponse = Blockaid.Token.TokenScanResponse;

export type ReportTransactionWarningEvent =
Blockaid.Stellar.TransactionReportParams["event"];

export class BlockAidService {
blockAidClient: Blockaid;
logger: Logger;
Expand Down Expand Up @@ -74,8 +77,16 @@ export class BlockAidService {
transaction: txXdr,
account_address: source,
};
const data = await this.blockAidClient.stellar.transaction.scan(body);
return { data, error: null };
const response = await this.blockAidClient.stellar.transaction
.scan(body)
.withResponse();
const request_id = response.response.headers.get("x-request-id");

const txData = {
...response.data,
request_id,
};
return { data: txData, error: null };
} catch (error) {
this.logger.error(error);
return { data: null, error: ERROR.UNABLE_TO_SCAN_TX };
Expand Down Expand Up @@ -131,4 +142,42 @@ export class BlockAidService {
};
}
};

reportAssetWarning = async (details: string, address: string) => {
try {
const data = await this.blockAidClient.token.report({
event: "FALSE_POSITIVE",
details,
report: {
type: "params",
params: { address, chain: "stellar" },
},
});
return { data, error: null };
} catch (error) {
this.logger.error(error);
return { error: ERROR.UNABLE_TO_REPORT_ASSET };
}
};

reportTransactionWarning = async (
details: string,
id: string,
event: ReportTransactionWarningEvent,
) => {
try {
const data = await this.blockAidClient.stellar.transaction.report({
details,
event,
report: {
id,
type: "request_id",
},
});
return { data, error: null };
} catch (error) {
this.logger.error(error);
return { error: ERROR.UNABLE_TO_REPORT_TRANSACTION };
}
};
}
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,10 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==

"@blockaid/client@^0.32.0":
version "0.32.0"
resolved "https://registry.yarnpkg.com/@blockaid/client/-/client-0.32.0.tgz#39081a199163b064a1fd240dbb1d4456a74383b7"
integrity sha512-14cf5hx24YW0etJiLDp6OHJnu+ainxUtC5k2+nNXk8jgVqwqS5+zRJhjt793DSfdaRKbQHPpyt11gd4p1JShAg==
"@blockaid/client@^0.34.0":
version "0.34.1"
resolved "https://registry.yarnpkg.com/@blockaid/client/-/client-0.34.1.tgz#3743d74f78ef3964feacb637db4c6d4b09c76282"
integrity sha512-4eHr+bb+NQx2xfq1eLHzN9K9xEdiaGU86wJkySeGkJQQMXs35iROHLVxGejA8V7iPSfrQzS318zYd9qOCtZo+A==
dependencies:
"@types/node" "^18.11.18"
"@types/node-fetch" "^2.6.4"
Expand Down

0 comments on commit 0817328

Please sign in to comment.