Skip to content

Commit b22d307

Browse files
committed
update sign message
1 parent 182dc7f commit b22d307

File tree

5 files changed

+124
-66
lines changed

5 files changed

+124
-66
lines changed

.github/workflows/publish.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ jobs:
2727
with:
2828
registry-url: "https://registry.npmjs.org"
2929
scope: "@zondax"
30-
- run: mv README-npm.md README.md
3130
- name: Install yarn
3231
run: npm install -g yarn
3332
- run: yarn install

README-npm.md

Lines changed: 0 additions & 12 deletions
This file was deleted.

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,40 @@ This package provides a basic client library to communicate with the Mina App ru
77

88
We recommend using the npmjs package in order to receive updates/fixes.
99

10+
### App Operations
11+
12+
| Operation | Response | Command | Notes |
13+
| ------------ | --------------------------- | ------- | ------------------------------------ |
14+
| getAppName | { name: string, version: string } | None | Returns app name and version |
15+
| getAppVersion| { version: string } | None | Returns app version |
16+
17+
### Address Operations
18+
19+
| Operation | Response | Command | Notes |
20+
| ------------ | --------------------------- | ------- | ------------------------------------ |
21+
| getAddress | { publicKey: string } | account + showAddrInDevice | Retrieves public key for given account |
22+
23+
### Transaction Operations
24+
25+
| Operation | Response | Command | Notes |
26+
| -------------- | --------------------------- | ----------------------------------------------------------------------- | ------------------------------------ |
27+
| signTransaction| { signature: string } | txType + senderAccount + senderAddress + receiverAddress + amount + fee + nonce + validUntil + memo + networkId | Signs a Mina transaction |
28+
| signMessage | { field: string, scalar: string, raw_signature: string, signed_message: string } | account + networkId + message | Signs a message using the specified account |
29+
30+
### Transaction Types
31+
32+
| Type | Value | Description |
33+
|------|-------|-------------|
34+
| PAYMENT | 0x00 | Payment transaction |
35+
| DELEGATION | 0x04 | Delegation transaction |
36+
37+
### Network IDs
38+
39+
| Network | Value | Description |
40+
|---------|-------|-------------|
41+
| MAINNET | 0x01 | Mina mainnet |
42+
| DEVNET | 0x00 | Mina devnet |
43+
1044
## Notes
1145

1246
Use `yarn install` to avoid issues.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"types": "./dist/index.d.ts",
2424
"typings": "./dist/index.d.ts",
2525
"files": [
26-
"dist/**"
26+
"dist/**",
27+
"README.md"
2728
],
2829
"scripts": {
2930
"build": "tsc",

src/app.ts

Lines changed: 88 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ interface SignTransactionResponse extends BaseLedgerResponse {
5555
}
5656

5757
interface SignMessageResponse extends BaseLedgerResponse {
58-
field: string | null;
59-
scalar: string | null;
60-
raw_signature?: string | null;
58+
field: string | null;
59+
scalar: string | null;
60+
raw_signature?: string | null;
61+
signed_message?: string | null;
6162
}
6263

6364

@@ -245,33 +246,49 @@ export class MinaApp extends BaseApp {
245246
}
246247
}
247248

248-
async signMessage(account: number, networkId: number, message: string): Promise<SignMessageResponse> {
249-
if (message.length === 0) {
250-
return {
251-
field: null,
252-
scalar: null,
253-
raw_signature: null,
254-
returnCode: "-6",
255-
message: "Message is empty",
256-
};
257-
}
258-
if (message.length > 255) {
259-
return {
260-
field: null,
261-
scalar: null,
262-
raw_signature: null,
263-
returnCode: "-7",
264-
message: "Message too long",
265-
};
266-
}
267-
try {
268-
const accountHex = Buffer.from(account.toString(16).padStart(8, '0'), 'hex');
269-
const networkIdHex = Buffer.from(networkId.toString(16).padStart(2, '0'), 'hex');
270-
const messageHex = Buffer.from(message, 'utf8');
271-
// Calculate total buffer length
272-
const totalLength = accountHex.length + networkIdHex.length + messageHex.length;
273-
// Create buffer with total length
274-
const dataTx = Buffer.concat([accountHex, networkIdHex, messageHex], totalLength);
249+
async signMessage(
250+
account: number,
251+
networkId: number,
252+
message: string,
253+
): Promise<SignMessageResponse> {
254+
if (message.length === 0) {
255+
return {
256+
field: null,
257+
scalar: null,
258+
raw_signature: null,
259+
signed_message: null,
260+
returnCode: "-6",
261+
message: "Message is empty",
262+
};
263+
}
264+
if (message.length > 255) {
265+
return {
266+
field: null,
267+
scalar: null,
268+
raw_signature: null,
269+
signed_message: null,
270+
returnCode: "-7",
271+
message: "Message too long",
272+
};
273+
}
274+
try {
275+
const accountHex = Buffer.from(
276+
account.toString(16).padStart(8, "0"),
277+
"hex",
278+
);
279+
const networkIdHex = Buffer.from(
280+
networkId.toString(16).padStart(2, "0"),
281+
"hex",
282+
);
283+
const messageHex = Buffer.from(message, "utf8");
284+
// Calculate total buffer length
285+
const totalLength =
286+
accountHex.length + networkIdHex.length + messageHex.length;
287+
// Create buffer with total length
288+
const dataTx = Buffer.concat(
289+
[accountHex, networkIdHex, messageHex],
290+
totalLength,
291+
);
275292

276293
const responseBuffer = await this.transport.send(
277294
this.CLA,
@@ -281,28 +298,47 @@ export class MinaApp extends BaseApp {
281298
dataTx
282299
);
283300

284-
const response = processResponse(responseBuffer)
285-
const signature = response.readBytes(response.length()).toString("hex");
286-
const sigLength = signature.length;
287-
const field_extracted = signature.substring(0, sigLength / 2);
288-
const scalar_extracted = signature.substring(sigLength / 2, sigLength);
289-
290-
return {
291-
field: BigInt("0x" + field_extracted).toString(),
292-
scalar: BigInt("0x" + scalar_extracted).toString(),
293-
raw_signature: signature,
294-
returnCode: "9000"
295-
};
296-
} catch (e) {
297-
const respError = processErrorResponse(e)
298-
return {
299-
field: null,
300-
scalar: null,
301-
raw_signature: null,
302-
returnCode: respError.returnCode.toString(),
303-
message: respError.errorMessage,
304-
};
305-
}
301+
const response = processResponse(responseBuffer);
302+
303+
// Validate minimum buffer length (64 bytes for signature + 1 byte for message length)
304+
if (response.length() < 65) {
305+
throw new Error("Response buffer too short");
306+
}
307+
308+
// First read the signature (64 bytes)
309+
const signature = response.readBytes(64).toString("hex");
310+
const sigLength = signature.length;
311+
const field_extracted = signature.substring(0, sigLength / 2);
312+
const scalar_extracted = signature.substring(sigLength / 2, sigLength);
313+
314+
// Then read the message length (1 byte)
315+
const messageLength = response.readBytes(1).readUInt8();
316+
317+
// Validate remaining buffer length against message length
318+
if (response.length() < messageLength) {
319+
throw new Error("Response buffer too short for message");
320+
}
321+
322+
// Finally read the message
323+
const returnedMessage = response.readBytes(messageLength).toString('utf8');
324+
325+
return {
326+
field: BigInt("0x" + field_extracted).toString(),
327+
scalar: BigInt("0x" + scalar_extracted).toString(),
328+
raw_signature: signature,
329+
signed_message: returnedMessage,
330+
returnCode: "9000",
331+
};
332+
} catch (e) {
333+
const respError = processErrorResponse(e);
334+
return {
335+
field: null,
336+
scalar: null,
337+
raw_signature: null,
338+
signed_message: null,
339+
returnCode: respError.returnCode.toString(),
340+
message: respError.errorMessage,
341+
};
306342
}
307343

308344

0 commit comments

Comments
 (0)