Skip to content

Commit d2fcaff

Browse files
✨ (btc-signer): Add steps to btc signer device action
1 parent f95176d commit d2fcaff

File tree

10 files changed

+322
-186
lines changed

10 files changed

+322
-186
lines changed

.changeset/plenty-books-teach.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-bitcoin": minor
3+
---
4+
5+
Add steps to btc signer device actions

packages/signer/signer-btc/src/api/app-binder/GetWalletAddressDeviceActionTypes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ import { type WalletSerializer } from "@internal/wallet/service/WalletSerializer
1717

1818
export type GetWalletAddressDAOutput = WalletAddress;
1919

20+
export const getWalletAddressDAStateSteps = Object.freeze({
21+
OPEN_APP: "signer.btc.steps.openApp",
22+
PREPARE_WALLET_POLICY: "signer.btc.steps.prepareWalletPolicy",
23+
GET_WALLET_ADDRESS: "signer.btc.steps.getWalletAddress",
24+
} as const);
25+
26+
export type GetWalletAddressDAStateStep =
27+
(typeof getWalletAddressDAStateSteps)[keyof typeof getWalletAddressDAStateSteps];
28+
2029
export type GetWalletAddressDAInput = {
2130
readonly skipOpenApp: boolean;
2231
readonly checkOnDevice: boolean;
@@ -38,6 +47,7 @@ type GetWalletAddressDARequiredInteraction =
3847

3948
export type GetWalletAddressDAIntermediateValue = {
4049
requiredUserInteraction: GetWalletAddressDARequiredInteraction;
50+
step: GetWalletAddressDAStateStep;
4151
};
4252

4353
export type GetWalletAddressDAState = DeviceActionState<

packages/signer/signer-btc/src/api/app-binder/SignPsbtDeviceActionTypes.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ import { type WalletSerializer } from "@internal/wallet/service/WalletSerializer
2121

2222
export type SignPsbtDAOutput = PsbtSignature[];
2323

24+
export const signPsbtDAStateSteps = Object.freeze({
25+
OPEN_APP: "signer.btc.steps.openApp",
26+
PREPARE_WALLET_POLICY: "signer.btc.steps.prepareWalletPolicy",
27+
BUILD_PSBT: "signer.btc.steps.buildPsbt",
28+
SIGN_PSBT: "signer.btc.steps.signPsbt",
29+
} as const);
30+
31+
export type SignPsbtDAStateStep =
32+
(typeof signPsbtDAStateSteps)[keyof typeof signPsbtDAStateSteps];
33+
2434
export type SignPsbtDAInput = {
2535
psbt: Psbt;
2636
wallet: ApiWallet;
@@ -42,6 +52,7 @@ export type SignPsbtDARequiredInteraction =
4252

4353
export type SignPsbtDAIntermediateValue = {
4454
requiredUserInteraction: SignPsbtDARequiredInteraction;
55+
step: SignPsbtDAStateStep;
4556
};
4657

4758
export type SignPsbtDAState = DeviceActionState<

packages/signer/signer-btc/src/api/app-binder/SignTransactionDeviceActionTypes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ import { type WalletSerializer } from "@internal/wallet/service/WalletSerializer
2121

2222
export type SignTransactionDAOutput = HexaString;
2323

24+
export const signTransactionDAStateSteps = Object.freeze({
25+
SIGN_PSBT: "signer.btc.steps.signPsbt",
26+
UPDATE_PSBT: "signer.btc.steps.updatePsbt",
27+
EXTRACT_TRANSACTION: "signer.btc.steps.extractTransaction",
28+
} as const);
29+
30+
export type SignTransactionDAStateStep =
31+
(typeof signTransactionDAStateSteps)[keyof typeof signTransactionDAStateSteps];
32+
2433
export type SignTransactionDAInput = {
2534
psbt: ApiPsbt;
2635
wallet: ApiWallet;
@@ -42,6 +51,7 @@ type SignTransactionDARequiredInteraction =
4251

4352
export type SignTransactionDAIntermediateValue = {
4453
requiredUserInteraction: SignTransactionDARequiredInteraction;
54+
step: SignTransactionDAStateStep;
4555
};
4656

4757
export type SignTransactionDAState = DeviceActionState<

packages/signer/signer-btc/src/internal/app-binder/device-action/GetWalletAddress/GetWalletAddressDeviceAction.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import {
66
UserInteractionRequired,
77
} from "@ledgerhq/device-management-kit";
88

9-
import { type GetWalletAddressDAState } from "@api/app-binder/GetWalletAddressDeviceActionTypes";
9+
import {
10+
type GetWalletAddressDAState,
11+
getWalletAddressDAStateSteps,
12+
} from "@api/app-binder/GetWalletAddressDeviceActionTypes";
1013
import { type RegisteredWallet, type WalletAddress } from "@api/model/Wallet";
1114
import { makeDeviceActionInternalApiMock } from "@internal/app-binder/device-action/__test-utils__/makeInternalApi";
1215
import { setupOpenAppDAMock } from "@internal/app-binder/device-action/__test-utils__/setupOpenAppDAMock";
@@ -76,24 +79,28 @@ describe("GetWalletAddressDeviceAction", () => {
7679
{
7780
intermediateValue: {
7881
requiredUserInteraction: UserInteractionRequired.None,
82+
step: getWalletAddressDAStateSteps.OPEN_APP,
7983
},
8084
status: DeviceActionStatus.Pending,
8185
},
8286
{
8387
intermediateValue: {
8488
requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,
89+
step: getWalletAddressDAStateSteps.OPEN_APP,
8590
},
8691
status: DeviceActionStatus.Pending,
8792
},
8893
{
8994
intermediateValue: {
9095
requiredUserInteraction: UserInteractionRequired.None,
96+
step: getWalletAddressDAStateSteps.PREPARE_WALLET_POLICY,
9197
},
9298
status: DeviceActionStatus.Pending,
9399
},
94100
{
95101
intermediateValue: {
96102
requiredUserInteraction: UserInteractionRequired.VerifyAddress,
103+
step: getWalletAddressDAStateSteps.GET_WALLET_ADDRESS,
97104
},
98105
status: DeviceActionStatus.Pending,
99106
},
@@ -151,12 +158,14 @@ describe("GetWalletAddressDeviceAction", () => {
151158
{
152159
intermediateValue: {
153160
requiredUserInteraction: UserInteractionRequired.None,
161+
step: getWalletAddressDAStateSteps.PREPARE_WALLET_POLICY,
154162
},
155163
status: DeviceActionStatus.Pending,
156164
},
157165
{
158166
intermediateValue: {
159167
requiredUserInteraction: UserInteractionRequired.VerifyAddress,
168+
step: getWalletAddressDAStateSteps.GET_WALLET_ADDRESS,
160169
},
161170
status: DeviceActionStatus.Pending,
162171
},
@@ -194,12 +203,14 @@ describe("GetWalletAddressDeviceAction", () => {
194203
status: DeviceActionStatus.Pending,
195204
intermediateValue: {
196205
requiredUserInteraction: UserInteractionRequired.None,
206+
step: getWalletAddressDAStateSteps.OPEN_APP,
197207
},
198208
},
199209
{
200210
status: DeviceActionStatus.Pending,
201211
intermediateValue: {
202212
requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,
213+
step: getWalletAddressDAStateSteps.OPEN_APP,
203214
},
204215
},
205216
{
@@ -271,18 +282,21 @@ describe("GetWalletAddressDeviceAction", () => {
271282
status: DeviceActionStatus.Pending,
272283
intermediateValue: {
273284
requiredUserInteraction: UserInteractionRequired.None,
285+
step: getWalletAddressDAStateSteps.OPEN_APP,
274286
},
275287
},
276288
{
277289
status: DeviceActionStatus.Pending,
278290
intermediateValue: {
279291
requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,
292+
step: getWalletAddressDAStateSteps.OPEN_APP,
280293
},
281294
},
282295
{
283296
status: DeviceActionStatus.Pending,
284297
intermediateValue: {
285298
requiredUserInteraction: UserInteractionRequired.None,
299+
step: getWalletAddressDAStateSteps.PREPARE_WALLET_POLICY,
286300
},
287301
},
288302
{
@@ -342,24 +356,28 @@ describe("GetWalletAddressDeviceAction", () => {
342356
status: DeviceActionStatus.Pending,
343357
intermediateValue: {
344358
requiredUserInteraction: UserInteractionRequired.None,
359+
step: getWalletAddressDAStateSteps.OPEN_APP,
345360
},
346361
},
347362
{
348363
status: DeviceActionStatus.Pending,
349364
intermediateValue: {
350365
requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,
366+
step: getWalletAddressDAStateSteps.OPEN_APP,
351367
},
352368
},
353369
{
354370
status: DeviceActionStatus.Pending,
355371
intermediateValue: {
356372
requiredUserInteraction: UserInteractionRequired.None,
373+
step: getWalletAddressDAStateSteps.PREPARE_WALLET_POLICY,
357374
},
358375
},
359376
{
360377
status: DeviceActionStatus.Pending,
361378
intermediateValue: {
362379
requiredUserInteraction: UserInteractionRequired.VerifyAddress,
380+
step: getWalletAddressDAStateSteps.GET_WALLET_ADDRESS,
363381
},
364382
},
365383
{

packages/signer/signer-btc/src/internal/app-binder/device-action/GetWalletAddress/GetWalletAddressDeviceAction.ts

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
type GetWalletAddressDAIntermediateValue,
1919
type GetWalletAddressDAInternalState,
2020
type GetWalletAddressDAOutput,
21+
getWalletAddressDAStateSteps,
2122
} from "@api/app-binder/GetWalletAddressDeviceActionTypes";
2223
import { type WalletAddress } from "@api/model/Wallet";
2324
import { type Wallet as ApiWallet } from "@api/model/Wallet";
@@ -114,19 +115,18 @@ export class GetWalletAddressDeviceAction extends XStateDeviceAction<
114115
/** @xstate-layout N4IgpgJg5mDOIC5QGUCWUB2AFMAnWA9hgIYA2AsnLMTACJgBuqAxmAILMAuqRAdAPIAHMBjaDB9Jqw7ciAYghEwvVBgYEA1soLDR45J2Kcw5YswAWqsAG0ADAF1EoQQVipZGJyAAeiACwAzADsvACcABwAjKGRtuG2AGyRSX4ANCAAnoiRAEwArLy2uX6RQUGRpeHhfgC+NelomDj4RGSUsNR0jCzsXDwYvADC5mDMGkIiYhLd0n1EAEpwAK6knHJ2jkggLm4eXr4IoRG8eTlFOaWhQX45QaHpWQiRN4UBfu8JeaE3obY5OXUGuhsHhCCQKFQaGBJD0ZP0hiMxhM9NMpL0PItYCs1tZIptnK53P19ogjuETmdcpdrrd7pl-M8wnkgvkgvFbH48n4EkFASBGiCWuD2p1oTN0fCBc0wW1ITAFEoVGpNMo3E1Qa0IR0oRsvDsiUQSU88tVeOEktEEuE8m8cjcHqScicgokTXk8rZygFQgD6vzgdLNSKoTDZh5eFKNcK5WA5HhcARcLxBKQjAAzRMAW14asFMq1ot1W31ey2B0iJr8ZotoStNpu9vpCDtoTNHr8PoizyKvL9kaFsu1XTRcL4-fzwZgmOxw1GGnWDj1hNLoAOFwCBWC5u5RySEQdT1sra+OSt1wCAQuzICfPHQZjoYlY4DUcHounq1nY3WeKXu2JZaIOum5sgkO61tE4QHhWBS2HkCT-G8R5wc8N58hgBAQHAXh3tGQ5iiOcyeMWy4AauiAALQJAeVGFLY9EMYxDG9kC6oDgWIbiqOAzIlMj7cX+BrEeRCCNo8sS2CcRz-B6zIsnBaGsXm974fxREInOvHiGpGLLKsgkrj4iBnrwFwVgkCHfEeCQBNB3K8IEpxBO6ySep8in+mxE4Plx6m4W+UIGWRRlPJEVRmncOTmhyLI2QeUS8GFQRvPBXZRLWt4vuxk4EbCflZd5+EfpwX4aEFhqAU84RRYUpyXmBATJBeQTQZEARhKEG5Ne69GUplXkqaKOmSkszCsB05XCSFOSXgUyVshUdoJLYF7QYkvAXkUER3H45q1qE-XKXhQ2+eGACiuAJrgk1GjN+S8PNUTFMtq1Nrckl-O6wTct6KF5HUdRAA */
115116
id: "GetWalletAddressDeviceAction",
116117
initial: "InitialState",
117-
context: ({ input }) => {
118-
return {
119-
input,
120-
intermediateValue: {
121-
requiredUserInteraction: UserInteractionRequired.None,
122-
},
123-
_internalState: {
124-
error: null,
125-
wallet: null,
126-
walletAddress: null,
127-
},
128-
};
129-
},
118+
context: ({ input }) => ({
119+
input,
120+
intermediateValue: {
121+
requiredUserInteraction: UserInteractionRequired.None,
122+
step: getWalletAddressDAStateSteps.OPEN_APP,
123+
},
124+
_internalState: {
125+
error: null,
126+
wallet: null,
127+
walletAddress: null,
128+
},
129+
}),
130130
states: {
131131
InitialState: {
132132
always: [
@@ -138,34 +138,34 @@ export class GetWalletAddressDeviceAction extends XStateDeviceAction<
138138
],
139139
},
140140
OpenAppDeviceAction: {
141-
exit: assign({
142-
intermediateValue: {
141+
entry: assign({
142+
intermediateValue: () => ({
143143
requiredUserInteraction: UserInteractionRequired.None,
144-
},
144+
step: getWalletAddressDAStateSteps.OPEN_APP,
145+
}),
145146
}),
146147
invoke: {
147148
id: "openAppStateMachine",
148149
input: { appName: "Bitcoin" },
149150
src: "openAppStateMachine",
150151
onSnapshot: {
151152
actions: assign({
152-
intermediateValue: (_) =>
153-
_.event.snapshot.context.intermediateValue,
153+
intermediateValue: ({ event }) => ({
154+
...event.snapshot.context.intermediateValue,
155+
step: getWalletAddressDAStateSteps.OPEN_APP,
156+
}),
154157
}),
155158
},
156159
onDone: {
157160
actions: assign({
158-
_internalState: (_) => {
159-
return _.event.output.caseOf<GetWalletAddressDAInternalState>(
160-
{
161-
Right: () => _.context._internalState,
162-
Left: (error) => ({
163-
..._.context._internalState,
164-
error,
165-
}),
166-
},
167-
);
168-
},
161+
_internalState: ({ event, context }) =>
162+
event.output.caseOf({
163+
Right: () => context._internalState,
164+
Left: (error) => ({
165+
...context._internalState,
166+
error,
167+
}),
168+
}),
169169
}),
170170
target: "CheckOpenAppDeviceActionResult",
171171
},
@@ -180,7 +180,14 @@ export class GetWalletAddressDeviceAction extends XStateDeviceAction<
180180
"Error",
181181
],
182182
},
183+
183184
PrepareWalletPolicy: {
185+
entry: assign({
186+
intermediateValue: () => ({
187+
requiredUserInteraction: UserInteractionRequired.None,
188+
step: getWalletAddressDAStateSteps.PREPARE_WALLET_POLICY,
189+
}),
190+
}),
184191
invoke: {
185192
id: "prepareWalletPolicy",
186193
src: "prepareWalletPolicy",
@@ -190,22 +197,20 @@ export class GetWalletAddressDeviceAction extends XStateDeviceAction<
190197
}),
191198
onDone: {
192199
target: "PrepareWalletPolicyResultCheck",
193-
actions: [
194-
assign({
195-
_internalState: ({ event, context }) => {
196-
if (isSuccessCommandResult(event.output)) {
197-
return {
198-
...context._internalState,
199-
wallet: event.output.data,
200-
};
201-
}
200+
actions: assign({
201+
_internalState: ({ event, context }) => {
202+
if (isSuccessCommandResult(event.output)) {
202203
return {
203204
...context._internalState,
204-
error: event.output.error,
205+
wallet: event.output.data,
205206
};
206-
},
207-
}),
208-
],
207+
}
208+
return {
209+
...context._internalState,
210+
error: event.output.error,
211+
};
212+
},
213+
}),
209214
},
210215
onError: {
211216
target: "Error",
@@ -225,11 +230,13 @@ export class GetWalletAddressDeviceAction extends XStateDeviceAction<
225230
requiredUserInteraction: context.input.checkOnDevice
226231
? UserInteractionRequired.VerifyAddress
227232
: UserInteractionRequired.None,
233+
step: getWalletAddressDAStateSteps.GET_WALLET_ADDRESS,
228234
},
229235
})),
230236
exit: assign({
231237
intermediateValue: {
232238
requiredUserInteraction: UserInteractionRequired.None,
239+
step: getWalletAddressDAStateSteps.GET_WALLET_ADDRESS,
233240
},
234241
}),
235242
invoke: {
@@ -246,22 +253,20 @@ export class GetWalletAddressDeviceAction extends XStateDeviceAction<
246253
}),
247254
onDone: {
248255
target: "GetWalletAddressResultCheck",
249-
actions: [
250-
assign({
251-
_internalState: ({ event, context }) => {
252-
if (isSuccessCommandResult(event.output)) {
253-
return {
254-
...context._internalState,
255-
walletAddress: event.output.data,
256-
};
257-
}
256+
actions: assign({
257+
_internalState: ({ event, context }) => {
258+
if (isSuccessCommandResult(event.output)) {
258259
return {
259260
...context._internalState,
260-
error: event.output.error,
261+
walletAddress: event.output.data,
261262
};
262-
},
263-
}),
264-
],
263+
}
264+
return {
265+
...context._internalState,
266+
error: event.output.error,
267+
};
268+
},
269+
}),
265270
},
266271
onError: {
267272
target: "Error",

0 commit comments

Comments
 (0)