Skip to content

Commit 8f570e9

Browse files
authored
✨ (signer-eth) [DSDK-1017]: Add blind signing detection and reporting to sign device actions (#1398)
2 parents 5f80505 + 2e7263b commit 8f570e9

31 files changed

Lines changed: 1036 additions & 67 deletions

.changeset/calm-ducks-love.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ledgerhq/signer-utils": minor
3+
---
4+
5+
Add generateSignatureId utility for blind signing reports

.changeset/dirty-weeks-fly.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ledgerhq/context-module": minor
3+
---
4+
5+
Add source configuration to ContextModuleBuilder for blind signing reports

.changeset/tidy-onions-flow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ledgerhq/device-signer-kit-ethereum": minor
3+
---
4+
5+
Add blind signing detection and reporting to sign transaction and sign typed data device actions

apps/sample/src/providers/SignerEthProvider/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export const SignerEthProvider: React.FC<PropsWithChildren> = ({
6262
.setWeb3ChecksConfig(web3ChecksConfig)
6363
.setMetadataServiceConfig(metadataServiceConfig)
6464
.setDatasourceConfig(datasourceConfig)
65+
.setAppSource("device-management-kit-playground")
6566
.build();
6667
const newSigner = new SignerEthBuilder({
6768
dmk,

packages/signer/context-module/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ const contextModule = new ContextModuleBuilder({
7474
.build();
7575
```
7676

77+
You can set a source identifier that will be included in blind signing reports. This helps distinguish which integration triggered a blind signing event. The default value is `"third-party"`.
78+
79+
```ts
80+
const contextModule = new ContextModuleBuilder({
81+
originToken: "origin-token", // replace with your origin token
82+
})
83+
.setAppSource("my-app-name")
84+
.build();
85+
```
86+
7787
It is also possible to instantiate the context module without the default loaders.
7888

7989
```ts

packages/signer/context-module/src/ContextModuleBuilder.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { DefaultContextModule } from "./DefaultContextModule";
2525
const DEFAULT_CAL_URL = "https://crypto-assets-service.api.ledger.com/v1";
2626
const DEFAULT_WEB3_CHECKS_URL = "https://web3checks-backend.api.ledger.com/v3";
2727
const DEFAULT_METADATA_SERVICE_DOMAIN = "https://nft.api.live.ledger.com";
28-
const DEFAULT_REPORTER_URL = "https://blind-signing-reporting.api.ledger.com";
28+
const DEFAULT_REPORTER_URL = "https://ingest.aws.stg.ldg-tech.com/ingest/v1";
2929

3030
/**
3131
* Default configuration for the context module
@@ -49,6 +49,7 @@ export const DEFAULT_CONFIG: Readonly<ContextModuleConfig> = Object.freeze({
4949
url: DEFAULT_REPORTER_URL,
5050
}),
5151
datasource: Object.freeze({ proxy: "default" }),
52+
appSource: "third-party",
5253
});
5354

5455
/**
@@ -181,6 +182,17 @@ export class ContextModuleBuilder {
181182
return this;
182183
}
183184

185+
/**
186+
* Set the app source identifier included in blind signing reports
187+
*
188+
* @param appSource
189+
* @returns this
190+
*/
191+
setAppSource(appSource: string) {
192+
this.config.appSource = appSource;
193+
return this;
194+
}
195+
184196
/**
185197
* Set a custom blind signing reporter
186198
*

packages/signer/context-module/src/DefaultContextModule.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ describe("DefaultContextModule", () => {
6262
datasource: {
6363
proxy: "default",
6464
},
65+
appSource: "third-party",
6566
originToken: "originToken",
6667
loggerFactory: mockLoggerFactory,
6768
};

packages/signer/context-module/src/config/model/ContextModuleConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export type ContextModuleConfig = {
3838
metadataServiceDomain: ContextModuleMetadataServiceConfig;
3939
reporter: ContextModuleReporterConfig;
4040
datasource: ContextModuleDatasourceConfig;
41+
appSource: string;
4142
};
4243

4344
export type ContextModuleServiceConfig = ContextModuleConfig & {

packages/signer/context-module/src/reporter/data/BlindSigningReporterDatasource.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,29 @@
11
import { type Either } from "purify-ts";
22

3-
import { type BlindSigningEventDto } from "./dto/BlindSigningEventDto";
3+
import {
4+
type BlindSigningMethod,
5+
type BlindSignReason,
6+
type ClearSigningType,
7+
} from "@/reporter/model/BlindSigningEvent";
8+
import { type BlindSigningModelId } from "@/reporter/model/BlindSigningModelId";
49

5-
export type BlindSigningReportParams = BlindSigningEventDto;
10+
export type BlindSigningReportEthContext = {
11+
clearSigningType: ClearSigningType;
12+
partialContextErrors: number;
13+
};
14+
15+
export type BlindSigningReportParams = {
16+
signatureId: string;
17+
signingMethod: BlindSigningMethod;
18+
isBlindSign: boolean;
19+
chainId: number | null;
20+
targetAddress: string | null;
21+
blindSignReason: BlindSignReason | null;
22+
modelId: BlindSigningModelId;
23+
signerAppVersion: string;
24+
deviceVersion: string | null;
25+
ethContext: BlindSigningReportEthContext | null;
26+
};
627

728
export interface BlindSigningReporterDatasource {
829
report(params: BlindSigningReportParams): Promise<Either<Error, void>>;

packages/signer/context-module/src/reporter/data/HttpBlindSigningReporterDatasource.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ describe("HttpBlindSigningReporterDatasource", () => {
2424
url: "https://reporter.test",
2525
},
2626
originToken: "originToken",
27+
appSource: "third-party",
2728
} as ContextModuleServiceConfig;
2829

2930
const params: BlindSigningReportParams = {
3031
signatureId: "a3f8Kb-1738850400000",
3132
signingMethod: BlindSigningMethod.ETH_SIGN_TRANSACTION,
32-
source: "ledger_wallet",
3333
isBlindSign: true,
3434
chainId: 1,
3535
targetAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
@@ -92,7 +92,7 @@ describe("HttpBlindSigningReporterDatasource", () => {
9292
expect(axios.request).toHaveBeenCalledWith(
9393
expect.objectContaining({
9494
method: "POST",
95-
url: `${config.reporter!.url}/v1/blind-signing-events`,
95+
url: `${config.reporter!.url}/blind-signing-events`,
9696
}),
9797
);
9898
});
@@ -116,7 +116,7 @@ describe("HttpBlindSigningReporterDatasource", () => {
116116
);
117117
});
118118

119-
it("should call axios with the event payload as data", async () => {
119+
it("should call axios with the event payload and injected source as data", async () => {
120120
// GIVEN
121121
vi.spyOn(axios, "request").mockResolvedValueOnce({ data: {} });
122122

@@ -127,7 +127,7 @@ describe("HttpBlindSigningReporterDatasource", () => {
127127
// THEN
128128
expect(axios.request).toHaveBeenCalledWith(
129129
expect.objectContaining({
130-
data: params,
130+
data: { ...params, source: config.appSource },
131131
}),
132132
);
133133
});

0 commit comments

Comments
 (0)