Skip to content

Commit fd7ff62

Browse files
authored
add generic chunking (#28)
1 parent 09de767 commit fd7ff62

File tree

4 files changed

+68
-9
lines changed

4 files changed

+68
-9
lines changed

src/app.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { MockTransport } from '@ledgerhq/hw-transport-mocker'
1717

1818
import BaseApp from './app'
1919
import { LedgerError } from './consts'
20+
import { ResponsePayload } from './payload'
2021
import { ResponseError } from './responseError'
2122

2223
describe('BaseApp', () => {
@@ -104,6 +105,51 @@ describe('BaseApp', () => {
104105
})
105106
})
106107

108+
describe('sendGenericChunk', () => {
109+
class TestBaseApp extends BaseApp {
110+
public async sendGenericChunk(ins: number, p2: number, chunkIdx: number, chunkNum: number, chunk: Buffer): Promise<ResponsePayload> {
111+
return super.sendGenericChunk(ins, p2, chunkIdx, chunkNum, chunk)
112+
}
113+
}
114+
115+
it('should send a generic chunk and receive a response', async () => {
116+
const responseBuffer = Buffer.concat([
117+
Buffer.from([0x01, 0x02, 0x03]), // Example response data
118+
Buffer.from([0x90, 0x00]), // Status code for no errors (0x9000)
119+
])
120+
121+
const transport = new MockTransport(responseBuffer)
122+
const app = new TestBaseApp(transport, params)
123+
const chunk = Buffer.from('generic chunk data')
124+
const response = await app.sendGenericChunk(0x00, 0x00, 1, 1, chunk)
125+
126+
expect(response.getCompleteBuffer()).toEqual(Buffer.from([0x01, 0x02, 0x03]))
127+
})
128+
129+
it('should handle errors correctly', async () => {
130+
const transport = new MockTransport(Buffer.alloc(0))
131+
const expectedException = ResponseError.fromReturnCode(LedgerError.UnknownTransportError)
132+
133+
transport.exchange = jest.fn().mockRejectedValue(expectedException)
134+
const app = new TestBaseApp(transport, params)
135+
136+
const someChunk = Buffer.from('generic chunk data')
137+
138+
await expect(app.sendGenericChunk(0x00, 0x00, 1, 1, someChunk)).rejects.toEqual(expectedException)
139+
})
140+
141+
it('should handle specific error codes', async () => {
142+
const errorBuffer = Buffer.from([0x6a, 0x80]) // Example error code (0x6a80)
143+
const transport = new MockTransport(errorBuffer)
144+
const app = new TestBaseApp(transport, params)
145+
146+
const someChunk = Buffer.from('generic chunk data')
147+
const expectedException = ResponseError.fromReturnCode(0x6a80)
148+
149+
await expect(app.sendGenericChunk(0x00, 0x00, 1, 1, someChunk)).rejects.toEqual(expectedException)
150+
})
151+
})
152+
107153
describe('getVersion', () => {
108154
it('should retrieve version information (5 bytes)', async () => {
109155
const responseBuffer = Buffer.concat([

src/app.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,18 @@ export default class BaseApp {
100100

101101
/**
102102
* Sends a chunk of data to the device and handles the response.
103-
* This method determines the payload type based on the chunk index and sends the chunk to the device.
104-
* It then processes the response from the device.
103+
* Determines the payload type based on the chunk index and sends the chunk to the device.
104+
* Processes the response from the device.
105105
*
106106
* @param ins - The instruction byte.
107+
* @param p2 - P2 parameter byte.
107108
* @param chunkIdx - The current chunk index.
108109
* @param chunkNum - The total number of chunks.
109110
* @param chunk - The chunk data as a buffer.
110111
* @returns A promise that resolves to the processed response from the device.
111112
* @throws {ResponseError} If the response from the device indicates an error.
112113
*/
113-
protected async signSendChunk(ins: number, chunkIdx: number, chunkNum: number, chunk: Buffer): Promise<ResponsePayload> {
114+
protected async sendGenericChunk(ins: number, p2: number, chunkIdx: number, chunkNum: number, chunk: Buffer): Promise<ResponsePayload> {
114115
let payloadType = PAYLOAD_TYPE.ADD
115116

116117
if (chunkIdx === 1) {
@@ -123,12 +124,28 @@ export default class BaseApp {
123124

124125
const statusList = [LedgerError.NoErrors, LedgerError.DataIsInvalid, LedgerError.BadKeyHandle]
125126

126-
const responseBuffer = await this.transport.send(this.CLA, ins, payloadType, 0, chunk, statusList)
127+
const responseBuffer = await this.transport.send(this.CLA, ins, payloadType, p2, chunk, statusList)
127128
const response = processResponse(responseBuffer)
128129

129130
return response
130131
}
131132

133+
/**
134+
* Sends a chunk of data to the device and handles the response.
135+
* This method determines the payload type based on the chunk index and sends the chunk to the device.
136+
* It then processes the response from the device.
137+
*
138+
* @param ins - The instruction byte.
139+
* @param chunkIdx - The current chunk index.
140+
* @param chunkNum - The total number of chunks.
141+
* @param chunk - The chunk data as a buffer.
142+
* @returns A promise that resolves to the processed response from the device.
143+
* @throws {ResponseError} If the response from the device indicates an error.
144+
*/
145+
protected async signSendChunk(ins: number, chunkIdx: number, chunkNum: number, chunk: Buffer): Promise<ResponsePayload> {
146+
return this.sendGenericChunk(ins, 0, chunkIdx, chunkNum, chunk)
147+
}
148+
132149
/**
133150
* Retrieves the version information from the device.
134151
* @returns A promise that resolves to the version information.

src/common.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,7 @@ export function processResponse(responseRaw: Buffer): ResponsePayload {
7878
}
7979

8080
// Construct and throw an error object with details
81-
throw {
82-
returnCode: returnCode,
83-
errorMessage: errorMessage,
84-
} as ResponseError
81+
throw new ResponseError(returnCode, errorMessage)
8582
}
8683

8784
/**

src/responseError.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ export class ResponseError extends Error {
3232
super(errorMessage)
3333
this.errorMessage = errorMessage
3434
this.returnCode = returnCode
35-
this.name = 'ResponseReturnCode'
3635
}
3736

3837
/**

0 commit comments

Comments
 (0)