@ledgerhq/hw-app-exchange 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+
2
+ > @ledgerhq/hw-app-exchange@0.1.0 build /home/runner/work/ledger-live/ledger-live/libs/ledgerjs/packages/hw-app-exchange
3
+ > tsc && tsc -m ES6 --outDir lib-es
4
+
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ <img src="https://user-images.githubusercontent.com/4631227/191834116-59cf590e-25cc-4956-ae5c-812ea464f324.png" height="100" />
2
+
3
+ [GitHub](https://github.com/LedgerHQ/ledger-live/),
4
+ [Ledger Devs Discord](https://developers.ledger.com/discord-pro),
5
+ [Developer Portal](https://developers.ledger.com/)
6
+
7
+ ## @ledgerhq/hw-app-exchange
8
+
9
+ Ledger Hardware Wallet Exchange app.
10
+
11
+ ## API
12
+
13
+ <!-- Generated by documentation.js. Update this documentation by updating the source code. -->
14
+
15
+ ### Table of Contents
package/jest.config.ts ADDED
@@ -0,0 +1,6 @@
1
+ import baseConfig from "../../jest.config";
2
+
3
+ export default {
4
+ ...baseConfig,
5
+ rootDir: __dirname,
6
+ };
@@ -0,0 +1,28 @@
1
+ /// <reference types="node" />
2
+ import Transport from "@ledgerhq/hw-transport";
3
+ import { BigNumber } from "bignumber.js";
4
+ export declare const enum RateTypes {
5
+ Fixed = 0,
6
+ Floating = 1
7
+ }
8
+ export declare const enum ExchangeTypes {
9
+ Swap = 0,
10
+ Sell = 1,
11
+ Fund = 2
12
+ }
13
+ export default class Exchange {
14
+ transport: Transport;
15
+ transactionType: ExchangeTypes;
16
+ transactionRate: RateTypes;
17
+ allowedStatuses: Array<number>;
18
+ constructor(transport: Transport, transactionType: ExchangeTypes, transactionRate?: RateTypes);
19
+ startNewTransaction(): Promise<string>;
20
+ setPartnerKey(partnerNameAndPublicKey: Buffer): Promise<void>;
21
+ checkPartner(signatureOfPartnerData: Buffer): Promise<void>;
22
+ processTransaction(transaction: Buffer, fee: BigNumber): Promise<void>;
23
+ checkTransactionSignature(transactionSignature: Buffer): Promise<void>;
24
+ checkPayoutAddress(payoutCurrencyConfig: Buffer, currencyConfigSignature: Buffer, addressParameters: Buffer): Promise<void>;
25
+ checkRefundAddress(refundCurrencyConfig: Buffer, currencyConfigSignature: Buffer, addressParameters: Buffer): Promise<void>;
26
+ signCoinTransaction(): Promise<void>;
27
+ }
28
+ //# sourceMappingURL=Exchange.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Exchange.d.ts","sourceRoot":"","sources":["../src/Exchange.ts"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,0BAAkB,SAAS;IACzB,KAAK,IAAO;IACZ,QAAQ,IAAO;CAChB;AAED,0BAAkB,aAAa;IAC7B,IAAI,IAAO;IACX,IAAI,IAAO;IACX,IAAI,IAAO;CACZ;AAqBD,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,EAAE,aAAa,CAAC;IAC/B,eAAe,EAAE,SAAS,CAAC;IAC3B,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAG5B;gBAGA,SAAS,EAAE,SAAS,EACpB,eAAe,EAAE,aAAa,EAC9B,eAAe,CAAC,EAAE,SAAS;IAOvB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC;IAqBtC,aAAa,CAAC,uBAAuB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7D,YAAY,CAAC,sBAAsB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY3D,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBtE,yBAAyB,CAAC,oBAAoB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYtE,kBAAkB,CACtB,oBAAoB,EAAE,MAAM,EAC5B,uBAAuB,EAAE,MAAM,EAC/B,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,CAAC;IA4BV,kBAAkB,CACtB,oBAAoB,EAAE,MAAM,EAC5B,uBAAuB,EAAE,MAAM,EAC/B,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,CAAC;IA0BV,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;CAW3C"}
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ exports.__esModule = true;
42
+ var errors_1 = require("@ledgerhq/errors");
43
+ var invariant_1 = __importDefault(require("invariant"));
44
+ var START_NEW_TRANSACTION_COMMAND = 0x03;
45
+ var SET_PARTNER_KEY_COMMAND = 0x04;
46
+ var CHECK_PARTNER_COMMAND = 0x05;
47
+ var PROCESS_TRANSACTION_RESPONSE = 0x06;
48
+ var CHECK_TRANSACTION_SIGNATURE = 0x07;
49
+ var CHECK_PAYOUT_ADDRESS = 0x08;
50
+ var CHECK_ASSET_IN = 0x08;
51
+ var CHECK_REFUND_ADDRESS = 0x09;
52
+ var SIGN_COIN_TRANSACTION = 0x0a;
53
+ var maybeThrowProtocolError = function (result) {
54
+ (0, invariant_1["default"])(result.length >= 2, "ExchangeTransport: Unexpected result length");
55
+ var resultCode = result.readUInt16BE(result.length - 2);
56
+ if (resultCode !== 0x9000) {
57
+ throw new errors_1.TransportStatusError(resultCode);
58
+ }
59
+ };
60
+ var Exchange = /** @class */ (function () {
61
+ function Exchange(transport, transactionType, transactionRate) {
62
+ this.allowedStatuses = [
63
+ 0x9000, 0x6a80, 0x6a81, 0x6a82, 0x6a83, 0x6a84, 0x6a85, 0x6e00, 0x6d00,
64
+ 0x9d1a,
65
+ ];
66
+ this.transactionType = transactionType;
67
+ this.transactionRate = transactionRate || 0 /* RateTypes.Fixed */;
68
+ this.transport = transport;
69
+ }
70
+ Exchange.prototype.startNewTransaction = function () {
71
+ return __awaiter(this, void 0, void 0, function () {
72
+ var result;
73
+ return __generator(this, function (_a) {
74
+ switch (_a.label) {
75
+ case 0: return [4 /*yield*/, this.transport.send(0xe0, START_NEW_TRANSACTION_COMMAND, this.transactionRate, this.transactionType, Buffer.alloc(0), this.allowedStatuses)];
76
+ case 1:
77
+ result = _a.sent();
78
+ maybeThrowProtocolError(result);
79
+ if (this.transactionType === 1 /* ExchangeTypes.Sell */ ||
80
+ this.transactionType === 2 /* ExchangeTypes.Fund */) {
81
+ return [2 /*return*/, result.slice(0, 32).toString("base64")];
82
+ }
83
+ return [2 /*return*/, result.toString("ascii", 0, 10)];
84
+ }
85
+ });
86
+ });
87
+ };
88
+ Exchange.prototype.setPartnerKey = function (partnerNameAndPublicKey) {
89
+ return __awaiter(this, void 0, void 0, function () {
90
+ var result;
91
+ return __generator(this, function (_a) {
92
+ switch (_a.label) {
93
+ case 0: return [4 /*yield*/, this.transport.send(0xe0, SET_PARTNER_KEY_COMMAND, this.transactionRate, this.transactionType, partnerNameAndPublicKey, this.allowedStatuses)];
94
+ case 1:
95
+ result = _a.sent();
96
+ maybeThrowProtocolError(result);
97
+ return [2 /*return*/];
98
+ }
99
+ });
100
+ });
101
+ };
102
+ Exchange.prototype.checkPartner = function (signatureOfPartnerData) {
103
+ return __awaiter(this, void 0, void 0, function () {
104
+ var result;
105
+ return __generator(this, function (_a) {
106
+ switch (_a.label) {
107
+ case 0: return [4 /*yield*/, this.transport.send(0xe0, CHECK_PARTNER_COMMAND, this.transactionRate, this.transactionType, signatureOfPartnerData, this.allowedStatuses)];
108
+ case 1:
109
+ result = _a.sent();
110
+ maybeThrowProtocolError(result);
111
+ return [2 /*return*/];
112
+ }
113
+ });
114
+ });
115
+ };
116
+ Exchange.prototype.processTransaction = function (transaction, fee) {
117
+ return __awaiter(this, void 0, void 0, function () {
118
+ var hex, feeHex, bufferToSend, result;
119
+ return __generator(this, function (_a) {
120
+ switch (_a.label) {
121
+ case 0:
122
+ hex = fee.toString(16);
123
+ hex = hex.padStart(hex.length + (hex.length % 2), "0");
124
+ feeHex = Buffer.from(hex, "hex");
125
+ bufferToSend = Buffer.concat([
126
+ Buffer.from([transaction.length]),
127
+ transaction,
128
+ Buffer.from([feeHex.length]),
129
+ feeHex,
130
+ ]);
131
+ return [4 /*yield*/, this.transport.send(0xe0, PROCESS_TRANSACTION_RESPONSE, this.transactionRate, this.transactionType, bufferToSend, this.allowedStatuses)];
132
+ case 1:
133
+ result = _a.sent();
134
+ maybeThrowProtocolError(result);
135
+ return [2 /*return*/];
136
+ }
137
+ });
138
+ });
139
+ };
140
+ Exchange.prototype.checkTransactionSignature = function (transactionSignature) {
141
+ return __awaiter(this, void 0, void 0, function () {
142
+ var result;
143
+ return __generator(this, function (_a) {
144
+ switch (_a.label) {
145
+ case 0: return [4 /*yield*/, this.transport.send(0xe0, CHECK_TRANSACTION_SIGNATURE, this.transactionRate, this.transactionType, transactionSignature, this.allowedStatuses)];
146
+ case 1:
147
+ result = _a.sent();
148
+ maybeThrowProtocolError(result);
149
+ return [2 /*return*/];
150
+ }
151
+ });
152
+ });
153
+ };
154
+ Exchange.prototype.checkPayoutAddress = function (payoutCurrencyConfig, currencyConfigSignature, addressParameters) {
155
+ return __awaiter(this, void 0, void 0, function () {
156
+ var bufferToSend, result;
157
+ return __generator(this, function (_a) {
158
+ switch (_a.label) {
159
+ case 0:
160
+ (0, invariant_1["default"])(payoutCurrencyConfig.length <= 255, "Currency config is too big");
161
+ (0, invariant_1["default"])(addressParameters.length <= 255, "Address parameter is too big.");
162
+ (0, invariant_1["default"])(currencyConfigSignature.length >= 67 &&
163
+ currencyConfigSignature.length <= 73, "Signature should be DER serialized and have length in [67, 73] bytes.");
164
+ bufferToSend = Buffer.concat([
165
+ Buffer.from([payoutCurrencyConfig.length]),
166
+ payoutCurrencyConfig,
167
+ currencyConfigSignature,
168
+ Buffer.from([addressParameters.length]),
169
+ addressParameters,
170
+ ]);
171
+ return [4 /*yield*/, this.transport.send(0xe0, this.transactionType === 0 /* ExchangeTypes.Swap */
172
+ ? CHECK_PAYOUT_ADDRESS
173
+ : CHECK_ASSET_IN, this.transactionRate, this.transactionType, bufferToSend, this.allowedStatuses)];
174
+ case 1:
175
+ result = _a.sent();
176
+ maybeThrowProtocolError(result);
177
+ return [2 /*return*/];
178
+ }
179
+ });
180
+ });
181
+ };
182
+ Exchange.prototype.checkRefundAddress = function (refundCurrencyConfig, currencyConfigSignature, addressParameters) {
183
+ return __awaiter(this, void 0, void 0, function () {
184
+ var bufferToSend, result;
185
+ return __generator(this, function (_a) {
186
+ switch (_a.label) {
187
+ case 0:
188
+ (0, invariant_1["default"])(refundCurrencyConfig.length <= 255, "Currency config is too big");
189
+ (0, invariant_1["default"])(addressParameters.length <= 255, "Address parameter is too big.");
190
+ (0, invariant_1["default"])(currencyConfigSignature.length >= 67 &&
191
+ currencyConfigSignature.length <= 73, "Signature should be DER serialized and have length in [67, 73] bytes.");
192
+ bufferToSend = Buffer.concat([
193
+ Buffer.from([refundCurrencyConfig.length]),
194
+ refundCurrencyConfig,
195
+ currencyConfigSignature,
196
+ Buffer.from([addressParameters.length]),
197
+ addressParameters,
198
+ ]);
199
+ return [4 /*yield*/, this.transport.send(0xe0, CHECK_REFUND_ADDRESS, this.transactionRate, this.transactionType, bufferToSend, this.allowedStatuses)];
200
+ case 1:
201
+ result = _a.sent();
202
+ maybeThrowProtocolError(result);
203
+ return [2 /*return*/];
204
+ }
205
+ });
206
+ });
207
+ };
208
+ Exchange.prototype.signCoinTransaction = function () {
209
+ return __awaiter(this, void 0, void 0, function () {
210
+ var result;
211
+ return __generator(this, function (_a) {
212
+ switch (_a.label) {
213
+ case 0: return [4 /*yield*/, this.transport.send(0xe0, SIGN_COIN_TRANSACTION, this.transactionRate, this.transactionType, Buffer.alloc(0), this.allowedStatuses)];
214
+ case 1:
215
+ result = _a.sent();
216
+ maybeThrowProtocolError(result);
217
+ return [2 /*return*/];
218
+ }
219
+ });
220
+ });
221
+ };
222
+ return Exchange;
223
+ }());
224
+ exports["default"] = Exchange;
225
+ //# sourceMappingURL=Exchange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Exchange.js","sourceRoot":"","sources":["../src/Exchange.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Exchange.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Exchange.test.d.ts","sourceRoot":"","sources":["../src/Exchange.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ exports.__esModule = true;
42
+ var hw_transport_mocker_1 = require("@ledgerhq/hw-transport-mocker");
43
+ var Exchange_1 = __importDefault(require("./Exchange"));
44
+ var util_1 = require("util");
45
+ describe("Contrustructor", function () {
46
+ [2 /* ExchangeTypes.Fund */, 1 /* ExchangeTypes.Sell */, 0 /* ExchangeTypes.Swap */].forEach(function (exchangeType) {
47
+ it("Exchange (value of ".concat(exchangeType, ") init with default rate types of fixed"), function () { return __awaiter(void 0, void 0, void 0, function () {
48
+ var transport, exchange;
49
+ return __generator(this, function (_a) {
50
+ switch (_a.label) {
51
+ case 0: return [4 /*yield*/, (0, hw_transport_mocker_1.openTransportReplayer)(hw_transport_mocker_1.RecordStore.fromString(""))];
52
+ case 1:
53
+ transport = _a.sent();
54
+ exchange = new Exchange_1["default"](transport, exchangeType);
55
+ expect(exchange.transactionRate).toBe(0 /* RateTypes.Fixed */);
56
+ return [2 /*return*/];
57
+ }
58
+ });
59
+ }); });
60
+ [0 /* RateTypes.Fixed */, 1 /* RateTypes.Floating */].forEach(function (rateType) {
61
+ it("Exchange (value of ".concat(exchangeType, ") init with rate types of value ").concat(rateType), function () { return __awaiter(void 0, void 0, void 0, function () {
62
+ var transport, exchange;
63
+ return __generator(this, function (_a) {
64
+ switch (_a.label) {
65
+ case 0: return [4 /*yield*/, (0, hw_transport_mocker_1.openTransportReplayer)(hw_transport_mocker_1.RecordStore.fromString(""))];
66
+ case 1:
67
+ transport = _a.sent();
68
+ exchange = new Exchange_1["default"](transport, exchangeType, rateType);
69
+ expect(exchange.transactionRate).toBe(rateType);
70
+ return [2 /*return*/];
71
+ }
72
+ });
73
+ }); });
74
+ });
75
+ });
76
+ });
77
+ describe("startNewTransaction", function () {
78
+ var textEncoder = new util_1.TextEncoder();
79
+ var mockResponse = "2ac38f187c"; // Response of length 10
80
+ it("sends a correct sequence of APDU", function () { return __awaiter(void 0, void 0, void 0, function () {
81
+ var recordStore, mockTransport, transport, exchange, result, expectCommand;
82
+ return __generator(this, function (_a) {
83
+ switch (_a.label) {
84
+ case 0:
85
+ recordStore = new hw_transport_mocker_1.RecordStore();
86
+ mockTransport = new hw_transport_mocker_1.MockTransport(Buffer.concat([
87
+ textEncoder.encode(mockResponse),
88
+ Buffer.from([0x90, 0x00]), // StatusCodes.OK
89
+ ]));
90
+ transport = (0, hw_transport_mocker_1.createTransportRecorder)(mockTransport, recordStore);
91
+ exchange = new Exchange_1["default"](new transport(mockTransport), 0 /* ExchangeTypes.Swap */);
92
+ return [4 /*yield*/, exchange.startNewTransaction()];
93
+ case 1:
94
+ result = _a.sent();
95
+ expectCommand = Buffer.from([
96
+ 0xe0,
97
+ 0x03,
98
+ 0 /* ExchangeTypes.Swap */,
99
+ 0 /* RateTypes.Fixed */,
100
+ 0x00, // Data
101
+ ]).toString("hex");
102
+ expect(recordStore.queue[0][0]).toBe(expectCommand);
103
+ expect(result).toEqual(mockResponse);
104
+ return [2 /*return*/];
105
+ }
106
+ });
107
+ }); });
108
+ // TOFIX: TransportError is not recognize as an Error type
109
+ xit("throws an error if status is not ok", function () { return __awaiter(void 0, void 0, void 0, function () {
110
+ var recordStore, mockTransport, transport, exchange;
111
+ return __generator(this, function (_a) {
112
+ recordStore = new hw_transport_mocker_1.RecordStore();
113
+ mockTransport = new hw_transport_mocker_1.MockTransport(Buffer.concat([
114
+ textEncoder.encode(mockResponse),
115
+ Buffer.from([0x6a, 0x80]),
116
+ ]));
117
+ transport = (0, hw_transport_mocker_1.createTransportRecorder)(mockTransport, recordStore);
118
+ exchange = new Exchange_1["default"](new transport(mockTransport), 0 /* ExchangeTypes.Swap */);
119
+ // When & Then
120
+ expect(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
121
+ switch (_a.label) {
122
+ case 0: return [4 /*yield*/, exchange.startNewTransaction()];
123
+ case 1: return [2 /*return*/, _a.sent()];
124
+ }
125
+ }); }); }).toThrowError();
126
+ return [2 /*return*/];
127
+ });
128
+ }); });
129
+ });
130
+ //# sourceMappingURL=Exchange.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Exchange.test.js","sourceRoot":"","sources":["../src/Exchange.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /// <reference types="node" />
2
+ import Transport from "@ledgerhq/hw-transport";
3
+ import { BigNumber } from "bignumber.js";
4
+ export declare const enum RateTypes {
5
+ Fixed = 0,
6
+ Floating = 1
7
+ }
8
+ export declare const enum ExchangeTypes {
9
+ Swap = 0,
10
+ Sell = 1,
11
+ Fund = 2
12
+ }
13
+ export default class Exchange {
14
+ transport: Transport;
15
+ transactionType: ExchangeTypes;
16
+ transactionRate: RateTypes;
17
+ allowedStatuses: Array<number>;
18
+ constructor(transport: Transport, transactionType: ExchangeTypes, transactionRate?: RateTypes);
19
+ startNewTransaction(): Promise<string>;
20
+ setPartnerKey(partnerNameAndPublicKey: Buffer): Promise<void>;
21
+ checkPartner(signatureOfPartnerData: Buffer): Promise<void>;
22
+ processTransaction(transaction: Buffer, fee: BigNumber): Promise<void>;
23
+ checkTransactionSignature(transactionSignature: Buffer): Promise<void>;
24
+ checkPayoutAddress(payoutCurrencyConfig: Buffer, currencyConfigSignature: Buffer, addressParameters: Buffer): Promise<void>;
25
+ checkRefundAddress(refundCurrencyConfig: Buffer, currencyConfigSignature: Buffer, addressParameters: Buffer): Promise<void>;
26
+ signCoinTransaction(): Promise<void>;
27
+ }
28
+ //# sourceMappingURL=Exchange.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Exchange.d.ts","sourceRoot":"","sources":["../src/Exchange.ts"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,0BAAkB,SAAS;IACzB,KAAK,IAAO;IACZ,QAAQ,IAAO;CAChB;AAED,0BAAkB,aAAa;IAC7B,IAAI,IAAO;IACX,IAAI,IAAO;IACX,IAAI,IAAO;CACZ;AAqBD,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,EAAE,aAAa,CAAC;IAC/B,eAAe,EAAE,SAAS,CAAC;IAC3B,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAG5B;gBAGA,SAAS,EAAE,SAAS,EACpB,eAAe,EAAE,aAAa,EAC9B,eAAe,CAAC,EAAE,SAAS;IAOvB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC;IAqBtC,aAAa,CAAC,uBAAuB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7D,YAAY,CAAC,sBAAsB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY3D,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBtE,yBAAyB,CAAC,oBAAoB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYtE,kBAAkB,CACtB,oBAAoB,EAAE,MAAM,EAC5B,uBAAuB,EAAE,MAAM,EAC/B,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,CAAC;IA4BV,kBAAkB,CACtB,oBAAoB,EAAE,MAAM,EAC5B,uBAAuB,EAAE,MAAM,EAC/B,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,CAAC;IA0BV,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;CAW3C"}
@@ -0,0 +1,220 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ import { TransportStatusError } from "@ledgerhq/errors";
38
+ import invariant from "invariant";
39
+ var START_NEW_TRANSACTION_COMMAND = 0x03;
40
+ var SET_PARTNER_KEY_COMMAND = 0x04;
41
+ var CHECK_PARTNER_COMMAND = 0x05;
42
+ var PROCESS_TRANSACTION_RESPONSE = 0x06;
43
+ var CHECK_TRANSACTION_SIGNATURE = 0x07;
44
+ var CHECK_PAYOUT_ADDRESS = 0x08;
45
+ var CHECK_ASSET_IN = 0x08;
46
+ var CHECK_REFUND_ADDRESS = 0x09;
47
+ var SIGN_COIN_TRANSACTION = 0x0a;
48
+ var maybeThrowProtocolError = function (result) {
49
+ invariant(result.length >= 2, "ExchangeTransport: Unexpected result length");
50
+ var resultCode = result.readUInt16BE(result.length - 2);
51
+ if (resultCode !== 0x9000) {
52
+ throw new TransportStatusError(resultCode);
53
+ }
54
+ };
55
+ var Exchange = /** @class */ (function () {
56
+ function Exchange(transport, transactionType, transactionRate) {
57
+ this.allowedStatuses = [
58
+ 0x9000, 0x6a80, 0x6a81, 0x6a82, 0x6a83, 0x6a84, 0x6a85, 0x6e00, 0x6d00,
59
+ 0x9d1a,
60
+ ];
61
+ this.transactionType = transactionType;
62
+ this.transactionRate = transactionRate || 0 /* RateTypes.Fixed */;
63
+ this.transport = transport;
64
+ }
65
+ Exchange.prototype.startNewTransaction = function () {
66
+ return __awaiter(this, void 0, void 0, function () {
67
+ var result;
68
+ return __generator(this, function (_a) {
69
+ switch (_a.label) {
70
+ case 0: return [4 /*yield*/, this.transport.send(0xe0, START_NEW_TRANSACTION_COMMAND, this.transactionRate, this.transactionType, Buffer.alloc(0), this.allowedStatuses)];
71
+ case 1:
72
+ result = _a.sent();
73
+ maybeThrowProtocolError(result);
74
+ if (this.transactionType === 1 /* ExchangeTypes.Sell */ ||
75
+ this.transactionType === 2 /* ExchangeTypes.Fund */) {
76
+ return [2 /*return*/, result.slice(0, 32).toString("base64")];
77
+ }
78
+ return [2 /*return*/, result.toString("ascii", 0, 10)];
79
+ }
80
+ });
81
+ });
82
+ };
83
+ Exchange.prototype.setPartnerKey = function (partnerNameAndPublicKey) {
84
+ return __awaiter(this, void 0, void 0, function () {
85
+ var result;
86
+ return __generator(this, function (_a) {
87
+ switch (_a.label) {
88
+ case 0: return [4 /*yield*/, this.transport.send(0xe0, SET_PARTNER_KEY_COMMAND, this.transactionRate, this.transactionType, partnerNameAndPublicKey, this.allowedStatuses)];
89
+ case 1:
90
+ result = _a.sent();
91
+ maybeThrowProtocolError(result);
92
+ return [2 /*return*/];
93
+ }
94
+ });
95
+ });
96
+ };
97
+ Exchange.prototype.checkPartner = function (signatureOfPartnerData) {
98
+ return __awaiter(this, void 0, void 0, function () {
99
+ var result;
100
+ return __generator(this, function (_a) {
101
+ switch (_a.label) {
102
+ case 0: return [4 /*yield*/, this.transport.send(0xe0, CHECK_PARTNER_COMMAND, this.transactionRate, this.transactionType, signatureOfPartnerData, this.allowedStatuses)];
103
+ case 1:
104
+ result = _a.sent();
105
+ maybeThrowProtocolError(result);
106
+ return [2 /*return*/];
107
+ }
108
+ });
109
+ });
110
+ };
111
+ Exchange.prototype.processTransaction = function (transaction, fee) {
112
+ return __awaiter(this, void 0, void 0, function () {
113
+ var hex, feeHex, bufferToSend, result;
114
+ return __generator(this, function (_a) {
115
+ switch (_a.label) {
116
+ case 0:
117
+ hex = fee.toString(16);
118
+ hex = hex.padStart(hex.length + (hex.length % 2), "0");
119
+ feeHex = Buffer.from(hex, "hex");
120
+ bufferToSend = Buffer.concat([
121
+ Buffer.from([transaction.length]),
122
+ transaction,
123
+ Buffer.from([feeHex.length]),
124
+ feeHex,
125
+ ]);
126
+ return [4 /*yield*/, this.transport.send(0xe0, PROCESS_TRANSACTION_RESPONSE, this.transactionRate, this.transactionType, bufferToSend, this.allowedStatuses)];
127
+ case 1:
128
+ result = _a.sent();
129
+ maybeThrowProtocolError(result);
130
+ return [2 /*return*/];
131
+ }
132
+ });
133
+ });
134
+ };
135
+ Exchange.prototype.checkTransactionSignature = function (transactionSignature) {
136
+ return __awaiter(this, void 0, void 0, function () {
137
+ var result;
138
+ return __generator(this, function (_a) {
139
+ switch (_a.label) {
140
+ case 0: return [4 /*yield*/, this.transport.send(0xe0, CHECK_TRANSACTION_SIGNATURE, this.transactionRate, this.transactionType, transactionSignature, this.allowedStatuses)];
141
+ case 1:
142
+ result = _a.sent();
143
+ maybeThrowProtocolError(result);
144
+ return [2 /*return*/];
145
+ }
146
+ });
147
+ });
148
+ };
149
+ Exchange.prototype.checkPayoutAddress = function (payoutCurrencyConfig, currencyConfigSignature, addressParameters) {
150
+ return __awaiter(this, void 0, void 0, function () {
151
+ var bufferToSend, result;
152
+ return __generator(this, function (_a) {
153
+ switch (_a.label) {
154
+ case 0:
155
+ invariant(payoutCurrencyConfig.length <= 255, "Currency config is too big");
156
+ invariant(addressParameters.length <= 255, "Address parameter is too big.");
157
+ invariant(currencyConfigSignature.length >= 67 &&
158
+ currencyConfigSignature.length <= 73, "Signature should be DER serialized and have length in [67, 73] bytes.");
159
+ bufferToSend = Buffer.concat([
160
+ Buffer.from([payoutCurrencyConfig.length]),
161
+ payoutCurrencyConfig,
162
+ currencyConfigSignature,
163
+ Buffer.from([addressParameters.length]),
164
+ addressParameters,
165
+ ]);
166
+ return [4 /*yield*/, this.transport.send(0xe0, this.transactionType === 0 /* ExchangeTypes.Swap */
167
+ ? CHECK_PAYOUT_ADDRESS
168
+ : CHECK_ASSET_IN, this.transactionRate, this.transactionType, bufferToSend, this.allowedStatuses)];
169
+ case 1:
170
+ result = _a.sent();
171
+ maybeThrowProtocolError(result);
172
+ return [2 /*return*/];
173
+ }
174
+ });
175
+ });
176
+ };
177
+ Exchange.prototype.checkRefundAddress = function (refundCurrencyConfig, currencyConfigSignature, addressParameters) {
178
+ return __awaiter(this, void 0, void 0, function () {
179
+ var bufferToSend, result;
180
+ return __generator(this, function (_a) {
181
+ switch (_a.label) {
182
+ case 0:
183
+ invariant(refundCurrencyConfig.length <= 255, "Currency config is too big");
184
+ invariant(addressParameters.length <= 255, "Address parameter is too big.");
185
+ invariant(currencyConfigSignature.length >= 67 &&
186
+ currencyConfigSignature.length <= 73, "Signature should be DER serialized and have length in [67, 73] bytes.");
187
+ bufferToSend = Buffer.concat([
188
+ Buffer.from([refundCurrencyConfig.length]),
189
+ refundCurrencyConfig,
190
+ currencyConfigSignature,
191
+ Buffer.from([addressParameters.length]),
192
+ addressParameters,
193
+ ]);
194
+ return [4 /*yield*/, this.transport.send(0xe0, CHECK_REFUND_ADDRESS, this.transactionRate, this.transactionType, bufferToSend, this.allowedStatuses)];
195
+ case 1:
196
+ result = _a.sent();
197
+ maybeThrowProtocolError(result);
198
+ return [2 /*return*/];
199
+ }
200
+ });
201
+ });
202
+ };
203
+ Exchange.prototype.signCoinTransaction = function () {
204
+ return __awaiter(this, void 0, void 0, function () {
205
+ var result;
206
+ return __generator(this, function (_a) {
207
+ switch (_a.label) {
208
+ case 0: return [4 /*yield*/, this.transport.send(0xe0, SIGN_COIN_TRANSACTION, this.transactionRate, this.transactionType, Buffer.alloc(0), this.allowedStatuses)];
209
+ case 1:
210
+ result = _a.sent();
211
+ maybeThrowProtocolError(result);
212
+ return [2 /*return*/];
213
+ }
214
+ });
215
+ });
216
+ };
217
+ return Exchange;
218
+ }());
219
+ export default Exchange;
220
+ //# sourceMappingURL=Exchange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Exchange.js","sourceRoot":"","sources":["../src/Exchange.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Exchange.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Exchange.test.d.ts","sourceRoot":"","sources":["../src/Exchange.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,125 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ import { createTransportRecorder, MockTransport, openTransportReplayer, RecordStore, } from "@ledgerhq/hw-transport-mocker";
38
+ import Exchange from "./Exchange";
39
+ import { TextEncoder } from "util";
40
+ describe("Contrustructor", function () {
41
+ [2 /* ExchangeTypes.Fund */, 1 /* ExchangeTypes.Sell */, 0 /* ExchangeTypes.Swap */].forEach(function (exchangeType) {
42
+ it("Exchange (value of ".concat(exchangeType, ") init with default rate types of fixed"), function () { return __awaiter(void 0, void 0, void 0, function () {
43
+ var transport, exchange;
44
+ return __generator(this, function (_a) {
45
+ switch (_a.label) {
46
+ case 0: return [4 /*yield*/, openTransportReplayer(RecordStore.fromString(""))];
47
+ case 1:
48
+ transport = _a.sent();
49
+ exchange = new Exchange(transport, exchangeType);
50
+ expect(exchange.transactionRate).toBe(0 /* RateTypes.Fixed */);
51
+ return [2 /*return*/];
52
+ }
53
+ });
54
+ }); });
55
+ [0 /* RateTypes.Fixed */, 1 /* RateTypes.Floating */].forEach(function (rateType) {
56
+ it("Exchange (value of ".concat(exchangeType, ") init with rate types of value ").concat(rateType), function () { return __awaiter(void 0, void 0, void 0, function () {
57
+ var transport, exchange;
58
+ return __generator(this, function (_a) {
59
+ switch (_a.label) {
60
+ case 0: return [4 /*yield*/, openTransportReplayer(RecordStore.fromString(""))];
61
+ case 1:
62
+ transport = _a.sent();
63
+ exchange = new Exchange(transport, exchangeType, rateType);
64
+ expect(exchange.transactionRate).toBe(rateType);
65
+ return [2 /*return*/];
66
+ }
67
+ });
68
+ }); });
69
+ });
70
+ });
71
+ });
72
+ describe("startNewTransaction", function () {
73
+ var textEncoder = new TextEncoder();
74
+ var mockResponse = "2ac38f187c"; // Response of length 10
75
+ it("sends a correct sequence of APDU", function () { return __awaiter(void 0, void 0, void 0, function () {
76
+ var recordStore, mockTransport, transport, exchange, result, expectCommand;
77
+ return __generator(this, function (_a) {
78
+ switch (_a.label) {
79
+ case 0:
80
+ recordStore = new RecordStore();
81
+ mockTransport = new MockTransport(Buffer.concat([
82
+ textEncoder.encode(mockResponse),
83
+ Buffer.from([0x90, 0x00]), // StatusCodes.OK
84
+ ]));
85
+ transport = createTransportRecorder(mockTransport, recordStore);
86
+ exchange = new Exchange(new transport(mockTransport), 0 /* ExchangeTypes.Swap */);
87
+ return [4 /*yield*/, exchange.startNewTransaction()];
88
+ case 1:
89
+ result = _a.sent();
90
+ expectCommand = Buffer.from([
91
+ 0xe0,
92
+ 0x03,
93
+ 0 /* ExchangeTypes.Swap */,
94
+ 0 /* RateTypes.Fixed */,
95
+ 0x00, // Data
96
+ ]).toString("hex");
97
+ expect(recordStore.queue[0][0]).toBe(expectCommand);
98
+ expect(result).toEqual(mockResponse);
99
+ return [2 /*return*/];
100
+ }
101
+ });
102
+ }); });
103
+ // TOFIX: TransportError is not recognize as an Error type
104
+ xit("throws an error if status is not ok", function () { return __awaiter(void 0, void 0, void 0, function () {
105
+ var recordStore, mockTransport, transport, exchange;
106
+ return __generator(this, function (_a) {
107
+ recordStore = new RecordStore();
108
+ mockTransport = new MockTransport(Buffer.concat([
109
+ textEncoder.encode(mockResponse),
110
+ Buffer.from([0x6a, 0x80]),
111
+ ]));
112
+ transport = createTransportRecorder(mockTransport, recordStore);
113
+ exchange = new Exchange(new transport(mockTransport), 0 /* ExchangeTypes.Swap */);
114
+ // When & Then
115
+ expect(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
116
+ switch (_a.label) {
117
+ case 0: return [4 /*yield*/, exchange.startNewTransaction()];
118
+ case 1: return [2 /*return*/, _a.sent()];
119
+ }
120
+ }); }); }).toThrowError();
121
+ return [2 /*return*/];
122
+ });
123
+ }); });
124
+ });
125
+ //# sourceMappingURL=Exchange.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Exchange.test.js","sourceRoot":"","sources":["../src/Exchange.test.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@ledgerhq/hw-app-exchange",
3
+ "version": "0.1.0",
4
+ "description": "Ledger Hardware Wallet Cosmos Application API",
5
+ "keywords": [
6
+ "Ledger",
7
+ "LedgerWallet",
8
+ "NanoS",
9
+ "Blue",
10
+ "Hardware Wallet"
11
+ ],
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/LedgerHQ/ledger-live.git"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/LedgerHQ/ledger-live/issues"
18
+ },
19
+ "homepage": "https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs/packages/hw-app-exchange",
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "main": "lib/Exchange.js",
24
+ "module": "lib-es/Exchange.js",
25
+ "types": "lib/Exchange.d.ts",
26
+ "license": "Apache-2.0",
27
+ "dependencies": {
28
+ "bignumber.js": "^9.1.0",
29
+ "invariant": "^2.2.2",
30
+ "@ledgerhq/errors": "^6.12.4-nightly.2",
31
+ "@ledgerhq/hw-transport": "^6.28.2-nightly.2"
32
+ },
33
+ "devDependencies": {
34
+ "@types/jest": "^29.5.0",
35
+ "@types/node": "^18.15.3",
36
+ "documentation": "13.2.4",
37
+ "jest": "^28.1.1",
38
+ "ts-jest": "^28.0.5",
39
+ "ts-node": "^10.4.0",
40
+ "typescript": "^4",
41
+ "@ledgerhq/hw-transport-mocker": "^6.27.13-nightly.2"
42
+ },
43
+ "scripts": {
44
+ "clean": "rimraf lib lib-es",
45
+ "build": "tsc && tsc -m ES6 --outDir lib-es",
46
+ "prewatch": "pnpm build",
47
+ "watch": "tsc --watch",
48
+ "doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts",
49
+ "lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx",
50
+ "lint:fix": "pnpm lint --fix",
51
+ "test": "jest"
52
+ }
53
+ }
@@ -0,0 +1,87 @@
1
+ import {
2
+ createTransportRecorder,
3
+ MockTransport,
4
+ openTransportReplayer,
5
+ RecordStore,
6
+ } from "@ledgerhq/hw-transport-mocker";
7
+ import Exchange, { ExchangeTypes, RateTypes } from "./Exchange";
8
+ import { TextEncoder } from "util";
9
+
10
+ describe("Contrustructor", () => {
11
+ [ExchangeTypes.Fund, ExchangeTypes.Sell, ExchangeTypes.Swap].forEach(
12
+ (exchangeType) => {
13
+ it(`Exchange (value of ${exchangeType}) init with default rate types of fixed`, async () => {
14
+ const transport = await openTransportReplayer(
15
+ RecordStore.fromString("")
16
+ );
17
+ const exchange = new Exchange(transport, exchangeType);
18
+ expect(exchange.transactionRate).toBe(RateTypes.Fixed);
19
+ });
20
+
21
+ [RateTypes.Fixed, RateTypes.Floating].forEach((rateType) => {
22
+ it(`Exchange (value of ${exchangeType}) init with rate types of value ${rateType}`, async () => {
23
+ const transport = await openTransportReplayer(
24
+ RecordStore.fromString("")
25
+ );
26
+ const exchange = new Exchange(transport, exchangeType, rateType);
27
+ expect(exchange.transactionRate).toBe(rateType);
28
+ });
29
+ });
30
+ }
31
+ );
32
+ });
33
+
34
+ describe("startNewTransaction", () => {
35
+ const textEncoder = new TextEncoder();
36
+ const mockResponse = "2ac38f187c"; // Response of length 10
37
+
38
+ it("sends a correct sequence of APDU", async () => {
39
+ // Given
40
+ const recordStore = new RecordStore();
41
+ const mockTransport = new MockTransport(
42
+ Buffer.concat([
43
+ textEncoder.encode(mockResponse),
44
+ Buffer.from([0x90, 0x00]), // StatusCodes.OK
45
+ ])
46
+ );
47
+ const transport = createTransportRecorder(mockTransport, recordStore);
48
+ const exchange = new Exchange(
49
+ new transport(mockTransport),
50
+ ExchangeTypes.Swap
51
+ );
52
+
53
+ // When
54
+ const result = await exchange.startNewTransaction();
55
+
56
+ // Then
57
+ const expectCommand = Buffer.from([
58
+ 0xe0,
59
+ 0x03, // Start Exchance
60
+ ExchangeTypes.Swap,
61
+ RateTypes.Fixed,
62
+ 0x00, // Data
63
+ ]).toString("hex");
64
+ expect(recordStore.queue[0][0]).toBe(expectCommand);
65
+ expect(result).toEqual(mockResponse);
66
+ });
67
+
68
+ // TOFIX: TransportError is not recognize as an Error type
69
+ xit("throws an error if status is not ok", async () => {
70
+ // Given
71
+ const recordStore = new RecordStore();
72
+ const mockTransport = new MockTransport(
73
+ Buffer.concat([
74
+ textEncoder.encode(mockResponse),
75
+ Buffer.from([0x6a, 0x80]),
76
+ ])
77
+ );
78
+ const transport = createTransportRecorder(mockTransport, recordStore);
79
+ const exchange = new Exchange(
80
+ new transport(mockTransport),
81
+ ExchangeTypes.Swap
82
+ );
83
+
84
+ // When & Then
85
+ expect(async () => await exchange.startNewTransaction()).toThrowError();
86
+ });
87
+ });
@@ -0,0 +1,206 @@
1
+ import Transport from "@ledgerhq/hw-transport";
2
+ import { BigNumber } from "bignumber.js";
3
+ import { TransportStatusError } from "@ledgerhq/errors";
4
+ import invariant from "invariant";
5
+
6
+ export const enum RateTypes {
7
+ Fixed = 0x00,
8
+ Floating = 0x01,
9
+ }
10
+
11
+ export const enum ExchangeTypes {
12
+ Swap = 0x00,
13
+ Sell = 0x01,
14
+ Fund = 0x02,
15
+ }
16
+
17
+ const START_NEW_TRANSACTION_COMMAND = 0x03;
18
+ const SET_PARTNER_KEY_COMMAND = 0x04;
19
+ const CHECK_PARTNER_COMMAND = 0x05;
20
+ const PROCESS_TRANSACTION_RESPONSE = 0x06;
21
+ const CHECK_TRANSACTION_SIGNATURE = 0x07;
22
+ const CHECK_PAYOUT_ADDRESS = 0x08;
23
+ const CHECK_ASSET_IN = 0x08;
24
+ const CHECK_REFUND_ADDRESS = 0x09;
25
+ const SIGN_COIN_TRANSACTION = 0x0a;
26
+
27
+ const maybeThrowProtocolError = (result: Buffer): void => {
28
+ invariant(result.length >= 2, "ExchangeTransport: Unexpected result length");
29
+ const resultCode = result.readUInt16BE(result.length - 2);
30
+
31
+ if (resultCode !== 0x9000) {
32
+ throw new TransportStatusError(resultCode);
33
+ }
34
+ };
35
+
36
+ export default class Exchange {
37
+ transport: Transport;
38
+ transactionType: ExchangeTypes;
39
+ transactionRate: RateTypes;
40
+ allowedStatuses: Array<number> = [
41
+ 0x9000, 0x6a80, 0x6a81, 0x6a82, 0x6a83, 0x6a84, 0x6a85, 0x6e00, 0x6d00,
42
+ 0x9d1a,
43
+ ];
44
+
45
+ constructor(
46
+ transport: Transport,
47
+ transactionType: ExchangeTypes,
48
+ transactionRate?: RateTypes
49
+ ) {
50
+ this.transactionType = transactionType;
51
+ this.transactionRate = transactionRate || RateTypes.Fixed;
52
+ this.transport = transport;
53
+ }
54
+
55
+ async startNewTransaction(): Promise<string> {
56
+ const result: Buffer = await this.transport.send(
57
+ 0xe0,
58
+ START_NEW_TRANSACTION_COMMAND,
59
+ this.transactionRate,
60
+ this.transactionType,
61
+ Buffer.alloc(0),
62
+ this.allowedStatuses
63
+ );
64
+ maybeThrowProtocolError(result);
65
+
66
+ if (
67
+ this.transactionType === ExchangeTypes.Sell ||
68
+ this.transactionType === ExchangeTypes.Fund
69
+ ) {
70
+ return result.slice(0, 32).toString("base64");
71
+ }
72
+
73
+ return result.toString("ascii", 0, 10);
74
+ }
75
+
76
+ async setPartnerKey(partnerNameAndPublicKey: Buffer): Promise<void> {
77
+ const result: Buffer = await this.transport.send(
78
+ 0xe0,
79
+ SET_PARTNER_KEY_COMMAND,
80
+ this.transactionRate,
81
+ this.transactionType,
82
+ partnerNameAndPublicKey,
83
+ this.allowedStatuses
84
+ );
85
+ maybeThrowProtocolError(result);
86
+ }
87
+
88
+ async checkPartner(signatureOfPartnerData: Buffer): Promise<void> {
89
+ const result: Buffer = await this.transport.send(
90
+ 0xe0,
91
+ CHECK_PARTNER_COMMAND,
92
+ this.transactionRate,
93
+ this.transactionType,
94
+ signatureOfPartnerData,
95
+ this.allowedStatuses
96
+ );
97
+ maybeThrowProtocolError(result);
98
+ }
99
+
100
+ async processTransaction(transaction: Buffer, fee: BigNumber): Promise<void> {
101
+ let hex: string = fee.toString(16);
102
+ hex = hex.padStart(hex.length + (hex.length % 2), "0");
103
+ const feeHex: Buffer = Buffer.from(hex, "hex");
104
+ const bufferToSend: Buffer = Buffer.concat([
105
+ Buffer.from([transaction.length]),
106
+ transaction,
107
+ Buffer.from([feeHex.length]),
108
+ feeHex,
109
+ ]);
110
+ const result: Buffer = await this.transport.send(
111
+ 0xe0,
112
+ PROCESS_TRANSACTION_RESPONSE,
113
+ this.transactionRate,
114
+ this.transactionType,
115
+ bufferToSend,
116
+ this.allowedStatuses
117
+ );
118
+ maybeThrowProtocolError(result);
119
+ }
120
+
121
+ async checkTransactionSignature(transactionSignature: Buffer): Promise<void> {
122
+ const result: Buffer = await this.transport.send(
123
+ 0xe0,
124
+ CHECK_TRANSACTION_SIGNATURE,
125
+ this.transactionRate,
126
+ this.transactionType,
127
+ transactionSignature,
128
+ this.allowedStatuses
129
+ );
130
+ maybeThrowProtocolError(result);
131
+ }
132
+
133
+ async checkPayoutAddress(
134
+ payoutCurrencyConfig: Buffer,
135
+ currencyConfigSignature: Buffer,
136
+ addressParameters: Buffer
137
+ ): Promise<void> {
138
+ invariant(payoutCurrencyConfig.length <= 255, "Currency config is too big");
139
+ invariant(addressParameters.length <= 255, "Address parameter is too big.");
140
+ invariant(
141
+ currencyConfigSignature.length >= 67 &&
142
+ currencyConfigSignature.length <= 73,
143
+ "Signature should be DER serialized and have length in [67, 73] bytes."
144
+ );
145
+ const bufferToSend: Buffer = Buffer.concat([
146
+ Buffer.from([payoutCurrencyConfig.length]),
147
+ payoutCurrencyConfig,
148
+ currencyConfigSignature,
149
+ Buffer.from([addressParameters.length]),
150
+ addressParameters,
151
+ ]);
152
+ const result: Buffer = await this.transport.send(
153
+ 0xe0,
154
+ this.transactionType === ExchangeTypes.Swap
155
+ ? CHECK_PAYOUT_ADDRESS
156
+ : CHECK_ASSET_IN,
157
+ this.transactionRate,
158
+ this.transactionType,
159
+ bufferToSend,
160
+ this.allowedStatuses
161
+ );
162
+ maybeThrowProtocolError(result);
163
+ }
164
+
165
+ async checkRefundAddress(
166
+ refundCurrencyConfig: Buffer,
167
+ currencyConfigSignature: Buffer,
168
+ addressParameters: Buffer
169
+ ): Promise<void> {
170
+ invariant(refundCurrencyConfig.length <= 255, "Currency config is too big");
171
+ invariant(addressParameters.length <= 255, "Address parameter is too big.");
172
+ invariant(
173
+ currencyConfigSignature.length >= 67 &&
174
+ currencyConfigSignature.length <= 73,
175
+ "Signature should be DER serialized and have length in [67, 73] bytes."
176
+ );
177
+ const bufferToSend: Buffer = Buffer.concat([
178
+ Buffer.from([refundCurrencyConfig.length]),
179
+ refundCurrencyConfig,
180
+ currencyConfigSignature,
181
+ Buffer.from([addressParameters.length]),
182
+ addressParameters,
183
+ ]);
184
+ const result: Buffer = await this.transport.send(
185
+ 0xe0,
186
+ CHECK_REFUND_ADDRESS,
187
+ this.transactionRate,
188
+ this.transactionType,
189
+ bufferToSend,
190
+ this.allowedStatuses
191
+ );
192
+ maybeThrowProtocolError(result);
193
+ }
194
+
195
+ async signCoinTransaction(): Promise<void> {
196
+ const result: Buffer = await this.transport.send(
197
+ 0xe0,
198
+ SIGN_COIN_TRANSACTION,
199
+ this.transactionRate,
200
+ this.transactionType,
201
+ Buffer.alloc(0),
202
+ this.allowedStatuses
203
+ );
204
+ maybeThrowProtocolError(result);
205
+ }
206
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "lib"
5
+ },
6
+ "include": ["src/**/*"]
7
+ }