Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
"private": true,
"packageManager": "pnpm@10.6.2",
"scripts": {
"build": "turbo run build --filter=gridplus-sdk --filter=@gridplus/btc",
"build": "turbo run build --filter=gridplus-sdk --filter=@gridplus/btc --filter=@gridplus/types",
"test": "turbo run test --filter=gridplus-sdk --filter=@gridplus/btc",
"test-unit": "turbo run test-unit --filter=gridplus-sdk --filter=@gridplus/btc",
"lint": "turbo run lint --filter=gridplus-sdk --filter=@gridplus/btc",
"lint:fix": "turbo run lint:fix --filter=gridplus-sdk --filter=@gridplus/btc",
"typecheck": "turbo run typecheck --filter=gridplus-sdk --filter=@gridplus/btc",
"lint": "turbo run lint --filter=gridplus-sdk --filter=@gridplus/btc --filter=@gridplus/types",
"lint:fix": "turbo run lint:fix --filter=gridplus-sdk --filter=@gridplus/btc --filter=@gridplus/types",
"typecheck": "turbo run typecheck --filter=gridplus-sdk --filter=@gridplus/btc --filter=@gridplus/types",
"e2e": "turbo run e2e --filter=gridplus-sdk",
"docs:build": "pnpm --filter gridplus-sdk-docs run build",
"docs:start": "pnpm --filter gridplus-sdk-docs run start"
Expand Down
1 change: 1 addition & 0 deletions packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
},
"dependencies": {
"@gridplus/btc": "workspace:*",
"@gridplus/types": "workspace:*",
"@ethereumjs/common": "^10.0.0",
"@ethereumjs/rlp": "^10.0.0",
"@ethereumjs/tx": "^10.0.0",
Expand Down
9 changes: 2 additions & 7 deletions packages/sdk/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,8 @@ const addressSizes = {
ETH: 20, // 20 byte address not including 0x prefix
} as const;

/** @internal */
const CURRENCIES = {
ETH: 'ETH',
BTC: 'BTC',
ETH_MSG: 'ETH_MSG',
} as const;
/** @internal - Re-export from @gridplus/types */
export { CURRENCIES } from '@gridplus/types';

/** @internal */
// THIS NEEDS TO BE A PROTOCOL CONSTANT TOO
Expand Down Expand Up @@ -646,7 +642,6 @@ export {
getFwVersionConst,
BIP_CONSTANTS,
BASE_URL,
CURRENCIES,
MAX_ADDR,
NETWORKS_BY_CHAIN_ID,
EXTERNAL_NETWORKS_BY_CHAIN_ID_URL,
Expand Down
222 changes: 18 additions & 204 deletions packages/sdk/src/protocol/latticeConstants.ts
Original file line number Diff line number Diff line change
@@ -1,204 +1,18 @@
export enum LatticeResponseCode {
success = 0x00,
invalidMsg = 0x80,
unsupportedVersion = 0x81,
deviceBusy = 0x82,
userTimeout = 0x83,
userDeclined = 0x84,
pairFailed = 0x85,
pairDisabled = 0x86,
permissionDisabled = 0x87,
internalError = 0x88,
gceTimeout = 0x89,
wrongWallet = 0x8a,
deviceLocked = 0x8b,
disabled = 0x8c,
already = 0x8d,
invalidEphemId = 0x8e,
}

export enum LatticeSecureMsgType {
connect = 0x01,
encrypted = 0x02,
}

export enum LatticeProtocolVersion {
v1 = 0x01,
}

export enum LatticeMsgType {
response = 0x00,
secure = 0x02,
}

export enum LatticeSecureEncryptedRequestType {
finalizePairing = 0,
getAddresses = 1,
sign = 3,
getWallets = 4,
getKvRecords = 7,
addKvRecords = 8,
removeKvRecords = 9,
fetchEncryptedData = 12,
test = 13,
}

export enum LatticeGetAddressesFlag {
none = 0, // For formatted addresses
secp256k1Pubkey = 3,
ed25519Pubkey = 4,
bls12_381Pubkey = 5,
secp256k1Xpub = 6, // For Bitcoin XPUB
}

export enum LatticeSignSchema {
bitcoin = 0,
ethereum = 1, // Deprecated
ethereumMsg = 3,
extraData = 4,
generic = 5,
}

export enum LatticeSignHash {
none = 0,
keccak256 = 1,
sha256 = 2,
}

export enum LatticeSignCurve {
secp256k1 = 0,
ed25519 = 1,
bls12_381 = 2,
}

export enum LatticeSignEncoding {
none = 1,
solana = 2,
evm = 4,
eth_deposit = 5,
eip7702_auth = 6,
eip7702_auth_list = 7,
}

export enum LatticeSignBlsDst {
NUL = 1,
POP = 2,
}

export enum LatticeEncDataSchema {
eip2335 = 0,
}

export const ProtocolConstants = {
// Lattice firmware uses a static initialization vector for
// message encryption/decryption. This is generally considered
// fine because each encryption/decryption uses a unique encryption
// secret (derived from the per-message ephemeral key pair).
aesIv: [
0x6d, 0x79, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x70, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64,
],
// Constant size of address buffers from the Lattice.
// Note that this size also captures public keys returned
// by the Lattice (addresses = strings, pubkeys = buffers)
addrStrLen: 129,
// Status of the client's pairing with the target Lattice
pairingStatus: {
notPaired: 0x00,
paired: 0x01,
},
// Response types, codes, and error messages
responseMsg: {
[LatticeResponseCode.success]: '',
[LatticeResponseCode.invalidMsg]: 'Invalid Request',
[LatticeResponseCode.unsupportedVersion]: 'Unsupported Version',
[LatticeResponseCode.deviceBusy]: 'Device Busy',
[LatticeResponseCode.userTimeout]: 'Timeout waiting for user',
[LatticeResponseCode.userDeclined]: 'Request declined by user',
[LatticeResponseCode.pairFailed]: 'Pairing failed',
[LatticeResponseCode.pairDisabled]: 'Pairing is currently disabled',
[LatticeResponseCode.permissionDisabled]:
'Automated signing is currently disabled',
[LatticeResponseCode.internalError]: 'Device Error',
[LatticeResponseCode.gceTimeout]: 'Device Timeout',
[LatticeResponseCode.wrongWallet]: 'Active wallet does not match request',
[LatticeResponseCode.deviceLocked]: 'Device Locked',
[LatticeResponseCode.disabled]: 'Feature Disabled',
[LatticeResponseCode.already]: 'Record already exists on device',
[LatticeResponseCode.invalidEphemId]: 'Request failed - needs resync',
},
msgSizes: {
// General message header size. Valid for all Lattice messages
header: 8,
// Checksum must be appended to each message
checksum: 4,
// Lattice secure message constants. All requests from this SDK
// are secure messages.
secure: {
// Sizes of full payloads for secure messages
payload: {
request: {
// [ requestType (1 byte) | pubkey (65 bytes) ]
connect: 66,
// [ requestType (1 byte) | ephemeralId (4 bytes) | encryptedData (1728 bytes) ]
encrypted: 1733,
},
// Note that the response payload always has status code as the
// first byte. This byte is removed as part of `request`, inside
// `parseLattice1Response`. These constants include the status
// code byte.
response: {
connect: 215,
// Encrypted responses are as follows:
// encryptedData (1728) | empty (1728)
// The latter half is empty due to an invalid type definition
// in Lattice firmware. (Someone made a C `struct` instead of
// a `union`, oops).
encrypted: 3457,
},
},
// Sizes for data inside secure message payloads
data: {
// All requests also have a `requestCode`, which is omitted
// from these constants.
request: {
connect: 65,
encrypted: {
// All encrypted requests are encrypted into a 1728 byte buffer
encryptedData: 1728,
// Individual request types have different data sizes.
[LatticeSecureEncryptedRequestType.finalizePairing]: 99,
[LatticeSecureEncryptedRequestType.getAddresses]: 54,
[LatticeSecureEncryptedRequestType.sign]: 1680,
[LatticeSecureEncryptedRequestType.getWallets]: 0,
[LatticeSecureEncryptedRequestType.getKvRecords]: 9,
[LatticeSecureEncryptedRequestType.addKvRecords]: 1391,
[LatticeSecureEncryptedRequestType.removeKvRecords]: 405,
[LatticeSecureEncryptedRequestType.fetchEncryptedData]: 1025,
[LatticeSecureEncryptedRequestType.test]: 506,
},
},
// All responses also have a `responseCode`, which is omitted
// from these constants.
response: {
encrypted: {
encryptedData: 1728,
// Once decrypted, the data size of the response
// payload will be determined by the request type.
// NOTE: All requests also have ephemeralPublicKey (65 bytes) and
// checksum (4 bytes), which are excluded from these sizes.
[LatticeSecureEncryptedRequestType.finalizePairing]: 0,
[LatticeSecureEncryptedRequestType.getAddresses]: 1290,
[LatticeSecureEncryptedRequestType.sign]: 1090,
[LatticeSecureEncryptedRequestType.getWallets]: 142,
[LatticeSecureEncryptedRequestType.getKvRecords]: 1395,
[LatticeSecureEncryptedRequestType.addKvRecords]: 0,
[LatticeSecureEncryptedRequestType.removeKvRecords]: 0,
[LatticeSecureEncryptedRequestType.fetchEncryptedData]: 1608,
[LatticeSecureEncryptedRequestType.test]: 1646,
},
},
},
},
},
} as const;
/**
* Re-export protocol enums and constants from @gridplus/types
*/
export {
LatticeResponseCode,
LatticeSecureMsgType,
LatticeProtocolVersion,
LatticeMsgType,
LatticeSecureEncryptedRequestType,
LatticeGetAddressesFlag,
LatticeSignSchema,
LatticeSignHash,
LatticeSignCurve,
LatticeSignEncoding,
LatticeSignBlsDst,
LatticeEncDataSchema,
ProtocolConstants,
} from '@gridplus/types';
94 changes: 13 additions & 81 deletions packages/sdk/src/types/client.ts
Original file line number Diff line number Diff line change
@@ -1,83 +1,15 @@
import type { Address, Hash } from 'viem';
import type { CURRENCIES } from '../constants';
import type { KeyPair } from './shared';

export type Currency = keyof typeof CURRENCIES;

export type SigningPath = number[];

/**
* Signature components as returned by the Lattice device.
* Values can be Buffer (raw) or string (hex) depending on context.
* Re-export client types from @gridplus/types
*/
export interface LatticeSignature {
r: Buffer | string;
s: Buffer | string;
v?: Buffer | string | number | bigint;
}

export interface SignData {
tx?: string;
txHash?: Hash;
changeRecipient?: string;
sig?: LatticeSignature;
sigs?: Buffer[];
signer?: Address;
pubkey?: Buffer;
err?: string;
}

export type SigningRequestResponse = SignData | { pubkey: null; sig: null };

/**
* @deprecated This type uses legacy field names and number types instead of viem-compatible bigint.
* Use viem's TransactionSerializable types directly, or create viem-aligned request types.
* This will be removed in a future version.
*/
export interface TransactionPayload {
type: number;
gasPrice: number;
nonce: number;
gasLimit: number;
to: string;
value: number;
data: string;
maxFeePerGas: number;
maxPriorityFeePerGas: number;
}

export interface Wallet {
/** 32 byte id */
uid: Buffer;
/** 20 char (max) string */
name: Buffer | null;
/** 4 byte flag */
capabilities: number;
/** External or internal wallet */
external: boolean;
}

export interface ActiveWallets {
internal: Wallet;
external: Wallet;
}

export interface RequestParams {
url: string;
payload: any; //TODO Fix this any
timeout?: number;
retries?: number;
}

export interface ClientStateData {
activeWallets: ActiveWallets;
ephemeralPub: KeyPair;
fwVersion: Buffer;
deviceId: string;
name: string;
baseUrl: string;
privKey: Buffer;
key: Buffer;
retryCount: number;
timeout: number;
}
export {
type Currency,
type SigningPath,
type LatticeSignature,
type SignData,
type SigningRequestResponse,
type TransactionPayload,
type Wallet,
type ActiveWallets,
type RequestParams,
type ClientStateData,
} from '@gridplus/types';
Loading
Loading