mirror of
https://github.com/trezor/trezor-suite.git
synced 2026-03-06 23:39:38 +01:00
chore: introduce protobuf and protocol packages
This commit is contained in:
@@ -55,7 +55,7 @@
|
||||
"format:verify": "yarn prettier --check \"**/*.{js,ts,tsx,mdx,md,html,json}\"",
|
||||
"update-submodules": "./scripts/update-submodules.sh",
|
||||
"update-coins": "./scripts/update-coins.sh",
|
||||
"update-protobuf": "yarn workspace @trezor/transport update:protobuf",
|
||||
"update-protobuf": "yarn workspace @trezor/protobuf update:protobuf",
|
||||
"update-coinjoin-middleware": "yarn workspace @trezor/suite-data update-coinjoin-middleware",
|
||||
"prepare-release": "./scripts/prepare-release.sh",
|
||||
"_______ Aliases _______": "Aliases for longer commands which we often have to run manually. Names don't have to be pretty or make total sense.",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"dependencies": {
|
||||
"@trezor/components": "workspace:*",
|
||||
"@trezor/connect-web": "workspace:*",
|
||||
"@trezor/transport": "workspace:*",
|
||||
"@trezor/protobuf": "workspace:*",
|
||||
"markdown-it": "^13.0.1",
|
||||
"markdown-it-link-attributes": "^4.0.1",
|
||||
"markdown-it-replace-link": "^1.2.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
CardanoNativeScriptHashDisplayFormat,
|
||||
CardanoTxSigningMode,
|
||||
} from '@trezor/transport/lib/types/messages';
|
||||
} from '@trezor/protobuf/lib/messages';
|
||||
|
||||
export const cardanoDerivationType = {
|
||||
name: 'derivationType',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CardanoAddressType } from '@trezor/transport/lib/types/messages';
|
||||
import { CardanoAddressType } from '@trezor/protobuf/lib/messages';
|
||||
|
||||
import { cardanoDerivationType } from './common';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CardanoNativeScriptType } from '@trezor/transport/lib/types/messages';
|
||||
import { CardanoNativeScriptType } from '@trezor/protobuf/lib/messages';
|
||||
|
||||
import { cardanoDerivationType, cardanoNativeScriptHashDisplayFormat } from './common';
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"references": [
|
||||
{ "path": "../components" },
|
||||
{ "path": "../connect-web" },
|
||||
{ "path": "../transport" }
|
||||
{ "path": "../protobuf" }
|
||||
],
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
|
||||
@@ -5,7 +5,7 @@ import CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||
import TerserPlugin from 'terser-webpack-plugin';
|
||||
|
||||
const COMMON_DATA_SRC = '../../packages/connect-common/files';
|
||||
const MESSAGES_SRC = '../../packages/transport/messages.json';
|
||||
const MESSAGES_SRC = '../../packages/protobuf/messages.json';
|
||||
|
||||
const DIST = path.resolve(__dirname, '../build');
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NETWORK_IDS, PROTOCOL_MAGICS } from '../../src/constants/cardano';
|
||||
import { CardanoAddressType } from '@trezor/transport/lib/types/messages';
|
||||
import { CardanoAddressType } from '@trezor/protobuf/lib/messages';
|
||||
|
||||
const legacyResults = [
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// @ts-ignore
|
||||
import commonFixtures from '../../../../submodules/trezor-common/tests/fixtures/cardano/get_base_address.derivations.json';
|
||||
|
||||
import { CardanoAddressType, CardanoDerivationType } from '@trezor/transport/lib/types/messages';
|
||||
import { CardanoAddressType, CardanoDerivationType } from '@trezor/protobuf/lib/messages';
|
||||
|
||||
export default {
|
||||
method: 'cardanoGetAddress',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
CardanoNativeScriptHashDisplayFormat,
|
||||
CardanoNativeScriptType,
|
||||
} from '@trezor/transport/lib/types/messages';
|
||||
} from '@trezor/protobuf/lib/messages';
|
||||
|
||||
export default {
|
||||
method: 'cardanoGetNativeScriptHash',
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
CardanoCertificateType,
|
||||
CardanoTxOutputSerializationFormat,
|
||||
CardanoTxSigningMode,
|
||||
} from '@trezor/transport/lib/types/messages';
|
||||
} from '@trezor/protobuf/lib/messages';
|
||||
|
||||
// vectors from https://github.com/trezor/trezor-firmware/tree/master/python/trezorlib/tests/device_tests/test_msg_cardano_sign_transaction.py
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fetch from 'cross-fetch';
|
||||
|
||||
import { EthereumDefinitions } from '@trezor/transport/lib/types/messages';
|
||||
import { EthereumDefinitions } from '@trezor/protobuf/lib/messages';
|
||||
|
||||
/**
|
||||
* For given chainId and optionally contractAddress download ethereum definitions for transaction signing.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// origin: https://github.com/trezor/connect/blob/develop/src/js/core/methods/helpers/ethereumSignTx.js
|
||||
|
||||
import { EthereumDefinitions } from '@trezor/transport/lib/types/messages';
|
||||
import { EthereumDefinitions } from '@trezor/protobuf/lib/messages';
|
||||
import { PROTO, ERRORS } from '../../constants';
|
||||
import type { TypedCall } from '../../device/DeviceCommands';
|
||||
import type { EthereumAccessList } from '../../types/api/ethereum';
|
||||
|
||||
@@ -3,4 +3,4 @@ export * as NETWORK from './network';
|
||||
export * as CARDANO from './cardano';
|
||||
export * as NEM from './nem';
|
||||
// NOTE: Protobuf file is intentionally exported directly
|
||||
export * as PROTO from '@trezor/transport/lib/types/messages';
|
||||
export * as PROTO from '@trezor/protobuf/lib/messages';
|
||||
|
||||
@@ -70,7 +70,7 @@ export type UnreadableDevice = {
|
||||
|
||||
export type Device = KnownDevice | UnknownDevice | UnreadableDevice;
|
||||
export type Features = PROTO.Features;
|
||||
export { DeviceModelInternal } from '@trezor/transport/lib/types/messages';
|
||||
export { DeviceModelInternal } from '@trezor/protobuf/lib/messages';
|
||||
|
||||
type FeaturesNarrowing =
|
||||
| {
|
||||
|
||||
@@ -12,7 +12,7 @@ export const getAssetByUrl = (url: string) => {
|
||||
case './data/firmware/2/releases.json':
|
||||
return require('@trezor/connect-common/files/firmware/2/releases.json');
|
||||
case './data/messages/messages.json':
|
||||
return require('@trezor/transport/messages.json');
|
||||
return require('@trezor/protobuf/messages.json');
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
5
packages/protobuf/.eslintrc.js
Normal file
5
packages/protobuf/.eslintrc.js
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
rules: {
|
||||
'@typescript-eslint/ban-types': 'off', // allow {} in protobuf.d.ts
|
||||
},
|
||||
};
|
||||
35
packages/protobuf/package.json
Normal file
35
packages/protobuf/package.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@trezor/protobuf",
|
||||
"version": "1.0.0",
|
||||
"license": "See LICENSE.md in repo root",
|
||||
"sideEffects": false,
|
||||
"main": "lib/index",
|
||||
"files": [
|
||||
"lib/",
|
||||
"!**/*.map",
|
||||
"scripts/protobuf-build.sh",
|
||||
"scripts/protobuf-patches",
|
||||
"scripts/protobuf-types.js",
|
||||
"messages.json"
|
||||
],
|
||||
"scripts": {
|
||||
"lint:js": "yarn g:eslint '**/*.{ts,tsx,js}'",
|
||||
"test:unit": "jest -c ../../jest.config.base.js --passWithNoTests",
|
||||
"type-check": "tsc --build",
|
||||
"build:lib": "rimraf ./lib && yarn tsc --build tsconfig.lib.json",
|
||||
"update:protobuf": "./scripts/protobuf-build.sh && npx prettier --write \"{messages.json,src/messages.ts}\"",
|
||||
"prepublishOnly": "yarn tsx ../../scripts/prepublishNPM.js",
|
||||
"prepublish": "yarn tsx ../../scripts/prepublish.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"bytebuffer": "^5.0.1",
|
||||
"long": "^4.0.0",
|
||||
"protobufjs": "7.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "^29.5.0",
|
||||
"rimraf": "^5.0.1",
|
||||
"tsx": "^3.12.7",
|
||||
"typescript": "4.9.5"
|
||||
}
|
||||
}
|
||||
@@ -198,7 +198,7 @@ export type TypedCall = <T extends MessageKey, R extends MessageKey>(
|
||||
`);
|
||||
|
||||
// save to file
|
||||
const filePath = path.join(__dirname, '../src/types/messages.ts');
|
||||
const filePath = path.join(__dirname, '../src/messages.ts');
|
||||
|
||||
fs.writeFile(filePath, lines.join('\n'), err => {
|
||||
if (err) return console.log(err);
|
||||
@@ -1,6 +1,7 @@
|
||||
import ByteBuffer from 'bytebuffer';
|
||||
import { Type, Message, Field } from 'protobufjs/light';
|
||||
import { isPrimitiveField } from '../../utils/protobuf';
|
||||
|
||||
import { isPrimitiveField } from './utils';
|
||||
|
||||
const transform = (field: Field, value: any) => {
|
||||
if (isPrimitiveField(field.type)) {
|
||||
@@ -41,9 +42,12 @@ const transform = (field: Field, value: any) => {
|
||||
throw new Error(`transport: decode: case not handled: ${field}`);
|
||||
};
|
||||
|
||||
function messageToJSON(Message: Message<Record<string, unknown>>, fields: Type['fields']) {
|
||||
export function messageToJSON(
|
||||
MessageParam: Message<Record<string, unknown>>,
|
||||
fields: Type['fields'],
|
||||
) {
|
||||
// get rid of Message.prototype references
|
||||
const { ...message } = Message;
|
||||
const { ...message } = MessageParam;
|
||||
const res: { [key: string]: any } = {};
|
||||
|
||||
Object.keys(fields).forEach(key => {
|
||||
@@ -61,10 +65,10 @@ function messageToJSON(Message: Message<Record<string, unknown>>, fields: Type['
|
||||
return res;
|
||||
}
|
||||
|
||||
export const decode = (Message: Type, data: ByteBuffer) => {
|
||||
export const decode = (MessageParam: Type, data: ByteBuffer) => {
|
||||
const buff = data.toBuffer();
|
||||
const a = new Uint8Array(buff);
|
||||
const decoded = Message.decode(a);
|
||||
const decoded = MessageParam.decode(a);
|
||||
|
||||
// [compatibility]: in the end it should be possible to get rid of messageToJSON method and call
|
||||
// Message.toObject(decoded) to return result as plain javascript object. This method should be able to do
|
||||
@@ -1,7 +1,7 @@
|
||||
import ByteBuffer from 'bytebuffer';
|
||||
import { Type } from 'protobufjs/light';
|
||||
|
||||
import { isPrimitiveField } from '../../utils/protobuf';
|
||||
import { isPrimitiveField } from './utils';
|
||||
|
||||
const transform = (fieldType: string, value: any) => {
|
||||
if (fieldType === 'bytes') {
|
||||
5
packages/protobuf/src/index.ts
Normal file
5
packages/protobuf/src/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './decode';
|
||||
export * from './encode';
|
||||
export * as Messages from './messages';
|
||||
export * from './types';
|
||||
export { parseConfigure, createMessageFromName, createMessageFromType } from './utils';
|
||||
6
packages/protobuf/src/types.ts
Normal file
6
packages/protobuf/src/types.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import * as Messages from './messages';
|
||||
|
||||
export type MessageFromTrezor = {
|
||||
type: keyof Messages.MessageType;
|
||||
message: Record<string, unknown>;
|
||||
};
|
||||
@@ -1,7 +1,40 @@
|
||||
// Module for loading the protobuf description from serialized description
|
||||
|
||||
import * as protobuf from 'protobufjs/light';
|
||||
import type { MessageFromTrezor } from '../../types';
|
||||
|
||||
import type { MessageFromTrezor } from './types';
|
||||
|
||||
const primitiveTypes = [
|
||||
'bool',
|
||||
'string',
|
||||
'bytes',
|
||||
'int32',
|
||||
'int64',
|
||||
'uint32',
|
||||
'uint64',
|
||||
'sint32',
|
||||
'sint64',
|
||||
'fixed32',
|
||||
'fixed64',
|
||||
'sfixed32',
|
||||
'sfixed64',
|
||||
'double',
|
||||
'float',
|
||||
];
|
||||
|
||||
/**
|
||||
* Determines whether given field is "primitive"
|
||||
* bool, strings, uint32 => true
|
||||
* HDNodeType => false
|
||||
*/
|
||||
export const isPrimitiveField = (field: any) => primitiveTypes.includes(field);
|
||||
|
||||
export function parseConfigure(data: protobuf.INamespace) {
|
||||
if (typeof data === 'string') {
|
||||
return protobuf.Root.fromJSON(JSON.parse(data));
|
||||
}
|
||||
return protobuf.Root.fromJSON(data);
|
||||
}
|
||||
|
||||
export const createMessageFromName = (messages: protobuf.Root, name: string) => {
|
||||
const Message = messages.lookupType(name);
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as ProtoBuf from 'protobufjs/light';
|
||||
|
||||
import { encode } from '../src/lowlevel/protobuf/encode';
|
||||
import { decode } from '../src/lowlevel/protobuf/decode';
|
||||
import { encode } from '../src/encode';
|
||||
import { decode } from '../src/decode';
|
||||
|
||||
const messages = {
|
||||
nested: {
|
||||
@@ -232,6 +232,7 @@ describe('basic concepts', () => {
|
||||
});
|
||||
|
||||
test('Different protobuf between receiving ends', () => {
|
||||
/* eslint-disable-next-line @typescript-eslint/no-shadow */
|
||||
const messages = {
|
||||
nested: {
|
||||
messages: {
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as ProtoBuf from 'protobufjs/light';
|
||||
|
||||
import { encode } from '../src/lowlevel/protobuf/encode';
|
||||
import { decode } from '../src/lowlevel/protobuf/decode';
|
||||
import { encode } from '../src/encode';
|
||||
import { decode } from '../src/decode';
|
||||
|
||||
const HDNodeType = {
|
||||
fields: {
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as protobuf from 'protobufjs/light';
|
||||
|
||||
import { createMessageFromName } from '../src/lowlevel/protobuf/messages';
|
||||
import { createMessageFromName } from '../src/utils';
|
||||
|
||||
const json = {
|
||||
nested: {
|
||||
6
packages/protobuf/tsconfig.json
Normal file
6
packages/protobuf/tsconfig.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": { "outDir": "libDev" },
|
||||
"include": ["src"],
|
||||
"references": []
|
||||
}
|
||||
7
packages/protobuf/tsconfig.lib.json
Normal file
7
packages/protobuf/tsconfig.lib.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig.lib.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
||||
24
packages/protocol/package.json
Normal file
24
packages/protocol/package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "@trezor/protocol",
|
||||
"version": "1.0.0",
|
||||
"license": "See LICENSE.md in repo root",
|
||||
"sideEffects": false,
|
||||
"main": "lib/index",
|
||||
"scripts": {
|
||||
"lint:js": "yarn g:eslint '**/*.{ts,tsx,js}'",
|
||||
"test:unit": "jest -c ../../jest.config.base.js --passWithNoTests",
|
||||
"type-check": "tsc --build",
|
||||
"build:lib": "rimraf ./lib && yarn tsc --build tsconfig.lib.json",
|
||||
"prepublishOnly": "yarn tsx ../../scripts/prepublishNPM.js",
|
||||
"prepublish": "yarn tsx ../../scripts/prepublish.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"bytebuffer": "^5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "^29.5.0",
|
||||
"rimraf": "^5.0.1",
|
||||
"tsx": "^3.12.7",
|
||||
"typescript": "4.9.5"
|
||||
}
|
||||
}
|
||||
1
packages/protocol/src/errors.ts
Normal file
1
packages/protocol/src/errors.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const PROTOCOL_MALFORMED = 'Malformed protocol format' as const;
|
||||
3
packages/protocol/src/index.ts
Normal file
3
packages/protocol/src/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * as v1 from './protocol-v1';
|
||||
export * as trzd from './protocol-trzd';
|
||||
export * from './errors';
|
||||
18
packages/protocol/src/protocol-trzd/decode.ts
Normal file
18
packages/protocol/src/protocol-trzd/decode.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import ByteBuffer from 'bytebuffer';
|
||||
|
||||
export const decode = (bytes: ArrayBuffer) => {
|
||||
const byteBuffer = ByteBuffer.wrap(bytes);
|
||||
const magic = byteBuffer.readBytes(5).toUTF8();
|
||||
const definitionType = byteBuffer.readUint8();
|
||||
const dataVersion = byteBuffer.readUint32();
|
||||
const protobufLength = byteBuffer.readUint8();
|
||||
const protobufPayload = byteBuffer.slice(12, 12 + protobufLength);
|
||||
|
||||
return {
|
||||
magic,
|
||||
definitionType,
|
||||
dataVersion,
|
||||
protobufLength,
|
||||
protobufPayload,
|
||||
};
|
||||
};
|
||||
@@ -1,2 +1 @@
|
||||
export * from './decode';
|
||||
export * from './encode';
|
||||
3
packages/protocol/src/protocol-v1/constants.ts
Normal file
3
packages/protocol/src/protocol-v1/constants.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const MESSAGE_HEADER_BYTE = 0x23;
|
||||
export const HEADER_SIZE = 1 + 1 + 4 + 2;
|
||||
export const BUFFER_SIZE = 63;
|
||||
@@ -1,6 +1,7 @@
|
||||
import ByteBuffer from 'bytebuffer';
|
||||
import { MESSAGE_HEADER_BYTE } from '../../constants';
|
||||
import * as ERRORS from '../../errors';
|
||||
|
||||
import * as ERRORS from '../errors';
|
||||
import { MESSAGE_HEADER_BYTE } from './constants';
|
||||
|
||||
/**
|
||||
* Reads meta information from buffer
|
||||
@@ -1,6 +1,6 @@
|
||||
import ByteBuffer from 'bytebuffer';
|
||||
|
||||
import { HEADER_SIZE, MESSAGE_HEADER_BYTE, BUFFER_SIZE } from '../../constants';
|
||||
import { HEADER_SIZE, MESSAGE_HEADER_BYTE, BUFFER_SIZE } from './constants';
|
||||
|
||||
type Options<Chunked> = {
|
||||
chunked: Chunked;
|
||||
5
packages/protocol/tsconfig.json
Normal file
5
packages/protocol/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": { "outDir": "libDev" },
|
||||
"references": []
|
||||
}
|
||||
7
packages/protocol/tsconfig.lib.json
Normal file
7
packages/protocol/tsconfig.lib.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig.lib.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
||||
@@ -4,7 +4,7 @@ module.exports = {
|
||||
'no-underscore-dangle': 'off',
|
||||
'no-restricted-syntax': 'off',
|
||||
'no-await-in-loop': 'off',
|
||||
'@typescript-eslint/ban-types': 'off', // allow {} in protobuf.d.ts
|
||||
'@typescript-eslint/ban-types': 'off', // still one file that needs refactoring
|
||||
'react-hooks/rules-of-hooks': 'off', // there is no react here
|
||||
},
|
||||
};
|
||||
|
||||
@@ -24,11 +24,7 @@
|
||||
},
|
||||
"files": [
|
||||
"lib/",
|
||||
"!**/*.map",
|
||||
"scripts/protobuf-build.sh",
|
||||
"scripts/protobuf-patches",
|
||||
"scripts/protobuf-types.js",
|
||||
"messages.json"
|
||||
"!**/*.map"
|
||||
],
|
||||
"scripts": {
|
||||
"lint:js": "yarn g:eslint '**/*.{ts,tsx,js}'",
|
||||
@@ -38,7 +34,6 @@
|
||||
"test:unit": "jest",
|
||||
"test:e2e": "ts-node -O '{\"module\": \"commonjs\", \"esModuleInterop\": true}' ./e2e/run.ts",
|
||||
"example:bridge": "jest --verbose -c jest.config.e2e.js --testPathPattern bridge.integration",
|
||||
"update:protobuf": "./scripts/protobuf-build.sh && yarn prettier --write \"{messages.json,src/types/messages.ts}\"",
|
||||
"prepublishOnly": "yarn tsx ../../scripts/prepublishNPM.js",
|
||||
"prepublish": "yarn tsx ../../scripts/prepublish.js"
|
||||
},
|
||||
@@ -55,12 +50,13 @@
|
||||
"typescript": "4.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trezor/protobuf": "workspace:*",
|
||||
"@trezor/protocol": "workspace:*",
|
||||
"@trezor/utils": "workspace:*",
|
||||
"bytebuffer": "^5.0.1",
|
||||
"cross-fetch": "^3.1.6",
|
||||
"json-stable-stringify": "^1.0.2",
|
||||
"long": "^4.0.0",
|
||||
"prettier": "2.8.8",
|
||||
"protobufjs": "7.2.4",
|
||||
"usb": "^2.9.0"
|
||||
}
|
||||
|
||||
@@ -88,4 +88,3 @@ export const ABORTED_BY_SIGNAL = 'Aborted by signal' as const;
|
||||
* see scheduleAction
|
||||
*/
|
||||
export const ABORTED_BY_TIMEOUT = 'Aborted by timeout' as const;
|
||||
export const PROTOCOL_MALFORMED = 'Malformed protocol format' as const;
|
||||
|
||||
@@ -11,14 +11,14 @@ export * as TRANSPORT_ERROR from './errors';
|
||||
protobuf.util.Long = Long;
|
||||
protobuf.configure();
|
||||
|
||||
export type { MessageFromTrezor, Descriptor } from './types';
|
||||
export type { Descriptor } from './types';
|
||||
export { TREZOR_USB_DESCRIPTORS, TRANSPORT } from './constants';
|
||||
|
||||
export { AbstractTransport as Transport } from './transports/abstract';
|
||||
|
||||
// messages are exported but there is no real need to use them elsewhere
|
||||
// transports have reference to this already
|
||||
export * as Messages from './types/messages';
|
||||
export { Messages } from '@trezor/protobuf';
|
||||
|
||||
// browser + node
|
||||
export { BridgeTransport } from './transports/bridge';
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import ByteBuffer from 'bytebuffer';
|
||||
import { Root } from 'protobufjs/light';
|
||||
|
||||
import * as decodeProtobuf from './protobuf/decode';
|
||||
import * as decodeProtocol from './protocol/decode';
|
||||
import { createMessageFromType } from './protobuf/messages';
|
||||
import { decode as decodeProtobuf, createMessageFromType } from '@trezor/protobuf';
|
||||
import { v1 as protocolV1 } from '@trezor/protocol';
|
||||
|
||||
export function receiveOne(messages: Root, data: string) {
|
||||
const bytebuffer = ByteBuffer.wrap(data, 'hex');
|
||||
|
||||
const { typeId, buffer } = decodeProtocol.decode(bytebuffer);
|
||||
const { typeId, buffer } = protocolV1.decode(bytebuffer);
|
||||
const { Message, messageName } = createMessageFromType(messages, typeId);
|
||||
const message = decodeProtobuf.decode(Message, buffer);
|
||||
const message = decodeProtobuf(Message, buffer);
|
||||
return {
|
||||
message,
|
||||
type: messageName,
|
||||
@@ -38,7 +37,7 @@ async function receiveRest(
|
||||
|
||||
async function receiveBuffer(receiver: () => Promise<ArrayBuffer>) {
|
||||
const data = await receiver();
|
||||
const { length, typeId, restBuffer } = decodeProtocol.decodeChunked(data);
|
||||
const { length, typeId, restBuffer } = protocolV1.decodeChunked(data);
|
||||
const decoded = new ByteBuffer(length);
|
||||
if (length) {
|
||||
decoded.append(restBuffer);
|
||||
@@ -51,7 +50,7 @@ export async function receiveAndParse(messages: Root, receiver: () => Promise<Ar
|
||||
const { received, typeId } = await receiveBuffer(receiver);
|
||||
const { Message, messageName } = createMessageFromType(messages, typeId);
|
||||
received.reset();
|
||||
const message = decodeProtobuf.decode(Message, received);
|
||||
const message = decodeProtobuf(Message, received);
|
||||
return {
|
||||
message,
|
||||
type: messageName,
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
//
|
||||
// Logic of "call" is broken to two parts - sending and receiving
|
||||
import { Root } from 'protobufjs/light';
|
||||
import { encode as encodeProtobuf } from './protobuf';
|
||||
import { encode as encodeProtocol } from './protocol';
|
||||
import { createMessageFromName } from './protobuf/messages';
|
||||
import { encode as encodeProtobuf, createMessageFromName } from '@trezor/protobuf';
|
||||
import { v1 as protocolV1 } from '@trezor/protocol';
|
||||
|
||||
// Sends more buffers to device.
|
||||
async function sendBuffers(sender: (data: Buffer) => Promise<void>, buffers: Array<Buffer>) {
|
||||
@@ -19,7 +18,7 @@ export function buildOne(messages: Root, name: string, data: Record<string, unkn
|
||||
const { Message, messageType } = createMessageFromName(messages, name);
|
||||
|
||||
const buffer = encodeProtobuf(Message, data);
|
||||
return encodeProtocol(buffer, {
|
||||
return protocolV1.encode(buffer, {
|
||||
addTrezorHeaders: false,
|
||||
chunked: false,
|
||||
messageType,
|
||||
@@ -29,7 +28,7 @@ export function buildOne(messages: Root, name: string, data: Record<string, unkn
|
||||
export const buildBuffers = (messages: Root, name: string, data: Record<string, unknown>) => {
|
||||
const { Message, messageType } = createMessageFromName(messages, name);
|
||||
const buffer = encodeProtobuf(Message, data);
|
||||
return encodeProtocol(buffer, {
|
||||
return protocolV1.encode(buffer, {
|
||||
addTrezorHeaders: true,
|
||||
chunked: true,
|
||||
messageType,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import * as protobuf from 'protobufjs/light';
|
||||
import { scheduleAction, ScheduleActionParams, ScheduledAction, Deferred } from '@trezor/utils';
|
||||
import { TypedEmitter } from '@trezor/utils/lib/typedEventEmitter';
|
||||
import { PROTOCOL_MALFORMED } from '@trezor/protocol';
|
||||
import { MessageFromTrezor } from '@trezor/protobuf';
|
||||
|
||||
import {
|
||||
MessageFromTrezor,
|
||||
Session,
|
||||
Descriptor,
|
||||
AbortableCall,
|
||||
@@ -256,7 +257,7 @@ export abstract class AbstractTransport extends TypedEmitter<{
|
||||
| typeof ERRORS.WRONG_RESULT_TYPE
|
||||
| typeof ERRORS.OTHER_CALL_IN_PROGRESS
|
||||
// webusb + bridge
|
||||
| typeof ERRORS.PROTOCOL_MALFORMED
|
||||
| typeof PROTOCOL_MALFORMED
|
||||
| typeof ERRORS.UNEXPECTED_ERROR
|
||||
| typeof ERRORS.SESSION_NOT_FOUND
|
||||
| typeof ERRORS.ABORTED_BY_TIMEOUT
|
||||
@@ -274,7 +275,7 @@ export abstract class AbstractTransport extends TypedEmitter<{
|
||||
| typeof ERRORS.WRONG_RESULT_TYPE
|
||||
| typeof ERRORS.OTHER_CALL_IN_PROGRESS
|
||||
// webusb + bridge
|
||||
| typeof ERRORS.PROTOCOL_MALFORMED
|
||||
| typeof PROTOCOL_MALFORMED
|
||||
| typeof ERRORS.DEVICE_DISCONNECTED_DURING_ACTION
|
||||
| typeof ERRORS.UNEXPECTED_ERROR
|
||||
| typeof ERRORS.SESSION_NOT_FOUND
|
||||
@@ -302,7 +303,7 @@ export abstract class AbstractTransport extends TypedEmitter<{
|
||||
| typeof ERRORS.OTHER_CALL_IN_PROGRESS
|
||||
// webusb + bridge
|
||||
| typeof ERRORS.DEVICE_DISCONNECTED_DURING_ACTION
|
||||
| typeof ERRORS.PROTOCOL_MALFORMED
|
||||
| typeof PROTOCOL_MALFORMED
|
||||
| typeof ERRORS.UNEXPECTED_ERROR
|
||||
| typeof ERRORS.ABORTED_BY_TIMEOUT
|
||||
| typeof ERRORS.ABORTED_BY_SIGNAL
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { versionUtils, createDeferred, Deferred, createTimeoutPromise } from '@trezor/utils';
|
||||
|
||||
import { PROTOCOL_MALFORMED } from '@trezor/protocol';
|
||||
import { bridgeApiCall } from '../utils/bridgeApiCall';
|
||||
import * as bridgeApiResult from '../utils/bridgeApiResult';
|
||||
import { buildOne } from '../lowlevel/send';
|
||||
@@ -318,7 +318,7 @@ export class BridgeTransport extends AbstractTransport {
|
||||
string,
|
||||
| BridgeCommonErrors
|
||||
| typeof ERRORS.DEVICE_DISCONNECTED_DURING_ACTION
|
||||
| typeof ERRORS.PROTOCOL_MALFORMED
|
||||
| typeof PROTOCOL_MALFORMED
|
||||
| typeof ERRORS.OTHER_CALL_IN_PROGRESS
|
||||
>;
|
||||
private async _post(
|
||||
@@ -332,7 +332,7 @@ export class BridgeTransport extends AbstractTransport {
|
||||
string,
|
||||
| BridgeCommonErrors
|
||||
| typeof ERRORS.DEVICE_DISCONNECTED_DURING_ACTION
|
||||
| typeof ERRORS.PROTOCOL_MALFORMED
|
||||
| typeof PROTOCOL_MALFORMED
|
||||
| typeof ERRORS.OTHER_CALL_IN_PROGRESS
|
||||
>;
|
||||
private async _post(
|
||||
@@ -342,7 +342,7 @@ export class BridgeTransport extends AbstractTransport {
|
||||
string,
|
||||
| BridgeCommonErrors
|
||||
| typeof ERRORS.DEVICE_DISCONNECTED_DURING_ACTION
|
||||
| typeof ERRORS.PROTOCOL_MALFORMED
|
||||
| typeof PROTOCOL_MALFORMED
|
||||
| typeof ERRORS.OTHER_CALL_IN_PROGRESS
|
||||
>;
|
||||
private async _post(
|
||||
@@ -390,6 +390,7 @@ export class BridgeTransport extends AbstractTransport {
|
||||
ERRORS.SESSION_NOT_FOUND,
|
||||
ERRORS.DEVICE_DISCONNECTED_DURING_ACTION,
|
||||
ERRORS.OTHER_CALL_IN_PROGRESS,
|
||||
PROTOCOL_MALFORMED,
|
||||
]);
|
||||
case '/enumerate':
|
||||
case '/listen':
|
||||
@@ -399,6 +400,7 @@ export class BridgeTransport extends AbstractTransport {
|
||||
ERRORS.SESSION_NOT_FOUND,
|
||||
ERRORS.DEVICE_DISCONNECTED_DURING_ACTION,
|
||||
ERRORS.OTHER_CALL_IN_PROGRESS,
|
||||
PROTOCOL_MALFORMED,
|
||||
]);
|
||||
case '/release':
|
||||
return this.unknownError(response.error, [
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { PROTOCOL_MALFORMED } from '@trezor/protocol';
|
||||
|
||||
import * as ERRORS from '../errors';
|
||||
|
||||
export type AnyError = (typeof ERRORS)[keyof typeof ERRORS];
|
||||
export type AnyError = (typeof ERRORS)[keyof typeof ERRORS] | typeof PROTOCOL_MALFORMED;
|
||||
|
||||
export interface Success<T> {
|
||||
success: true;
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
import * as Messages from './messages';
|
||||
|
||||
export * from './apiCall';
|
||||
|
||||
export type MessageFromTrezor = {
|
||||
type: keyof Messages.MessageType;
|
||||
message: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type Session = null | string;
|
||||
export type Descriptor = { path: string; session?: Session };
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import { success, error, unknownError } from './result';
|
||||
|
||||
import * as ERRORS from '../errors';
|
||||
|
||||
import { PROTOCOL_MALFORMED } from '@trezor/protocol';
|
||||
|
||||
export type HttpRequestOptions = {
|
||||
body?: Array<any> | Record<string, unknown> | string;
|
||||
url: string;
|
||||
@@ -97,10 +99,10 @@ export async function bridgeApiCall(options: HttpRequestOptions) {
|
||||
return error({ error: ERRORS.INTERFACE_UNABLE_TO_OPEN_DEVICE });
|
||||
}
|
||||
if (errStr === BRIDGE_MALFORMED_PROTOBUF) {
|
||||
return error({ error: ERRORS.PROTOCOL_MALFORMED });
|
||||
return error({ error: PROTOCOL_MALFORMED });
|
||||
}
|
||||
if (errStr === BRIDGE_MALFORMED_WIRE_FORMAT) {
|
||||
return error({ error: ERRORS.PROTOCOL_MALFORMED });
|
||||
return error({ error: PROTOCOL_MALFORMED });
|
||||
}
|
||||
return unknownError(new Error(errStr), [
|
||||
ERRORS.DEVICE_NOT_FOUND,
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
const primitiveTypes = [
|
||||
'bool',
|
||||
'string',
|
||||
'bytes',
|
||||
'int32',
|
||||
'int64',
|
||||
'uint32',
|
||||
'uint64',
|
||||
'sint32',
|
||||
'sint64',
|
||||
'fixed32',
|
||||
'fixed64',
|
||||
'sfixed32',
|
||||
'sfixed64',
|
||||
'double',
|
||||
'float',
|
||||
];
|
||||
|
||||
/**
|
||||
* Determines whether given field is "primitive"
|
||||
* bool, strings, uint32 => true
|
||||
* HDNodeType => false
|
||||
*/
|
||||
export const isPrimitiveField = (field: any) => primitiveTypes.includes(field);
|
||||
@@ -3,7 +3,7 @@ import { AbstractUsbTransport, UsbTransportConstructorParams } from '../src/tran
|
||||
import { UsbInterface } from '../src/interfaces/usb';
|
||||
import { SessionsClient } from '../src/sessions/client';
|
||||
import { SessionsBackground } from '../src/sessions/background';
|
||||
import * as messages from '../messages.json';
|
||||
import * as messages from '@trezor/protobuf/messages.json';
|
||||
|
||||
// we cant directly use abstract class (UsbTransport)
|
||||
class TestUsbTransport extends AbstractUsbTransport {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
{ "path": "../protobuf" },
|
||||
{ "path": "../protocol" },
|
||||
{ "path": "../utils" },
|
||||
{ "path": "../trezor-user-env-link" }
|
||||
]
|
||||
|
||||
33
yarn.lock
33
yarn.lock
@@ -7883,7 +7883,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@trezor/components": "workspace:*"
|
||||
"@trezor/connect-web": "workspace:*"
|
||||
"@trezor/transport": "workspace:*"
|
||||
"@trezor/protobuf": "workspace:*"
|
||||
"@types/markdown-it": ^12.2.3
|
||||
"@types/markdown-it-link-attributes": ^3.0.1
|
||||
"@types/react-router": ^5.1.20
|
||||
@@ -8067,6 +8067,8 @@ __metadata:
|
||||
"@trezor/blockchain-link-types": "workspace:*"
|
||||
"@trezor/connect-analytics": "workspace:*"
|
||||
"@trezor/connect-common": "workspace:*"
|
||||
"@trezor/protobuf": "workspace:*"
|
||||
"@trezor/protocol": "workspace:*"
|
||||
"@trezor/transport": "workspace:*"
|
||||
"@trezor/trezor-user-env-link": "workspace:*"
|
||||
"@trezor/utils": "workspace:*"
|
||||
@@ -8173,6 +8175,32 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@trezor/protobuf@workspace:*, @trezor/protobuf@workspace:packages/protobuf":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@trezor/protobuf@workspace:packages/protobuf"
|
||||
dependencies:
|
||||
bytebuffer: ^5.0.1
|
||||
jest: ^29.5.0
|
||||
long: ^4.0.0
|
||||
protobufjs: 7.2.4
|
||||
rimraf: ^5.0.1
|
||||
tsx: ^3.12.7
|
||||
typescript: 4.9.5
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@trezor/protocol@workspace:*, @trezor/protocol@workspace:packages/protocol":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@trezor/protocol@workspace:packages/protocol"
|
||||
dependencies:
|
||||
bytebuffer: ^5.0.1
|
||||
jest: ^29.5.0
|
||||
rimraf: ^5.0.1
|
||||
tsx: ^3.12.7
|
||||
typescript: 4.9.5
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@trezor/react-utils@workspace:*, @trezor/react-utils@workspace:packages/react-utils":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@trezor/react-utils@workspace:packages/react-utils"
|
||||
@@ -8727,6 +8755,8 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@trezor/transport@workspace:packages/transport"
|
||||
dependencies:
|
||||
"@trezor/protobuf": "workspace:*"
|
||||
"@trezor/protocol": "workspace:*"
|
||||
"@trezor/trezor-user-env-link": "workspace:*"
|
||||
"@trezor/utils": "workspace:*"
|
||||
"@types/bytebuffer": ^5.0.44
|
||||
@@ -8738,7 +8768,6 @@ __metadata:
|
||||
jest-environment-jsdom: ^29.5.0
|
||||
json-stable-stringify: ^1.0.2
|
||||
long: ^4.0.0
|
||||
prettier: 2.8.8
|
||||
protobufjs: 7.2.4
|
||||
rimraf: ^5.0.1
|
||||
ts-node: ^10.9.1
|
||||
|
||||
Reference in New Issue
Block a user