Skip to content

Commit

Permalink
v3.3.0 (#599)
Browse files Browse the repository at this point in the history
* adds bitcoin xpub support

* fix xpub handling

* adds eslint ignore

* bump to v3.3.0 (#598)

* bump to v3.3.0

* Update docs-build-deploy.yml

---------

Co-authored-by: Tomek Marciniak <[email protected]>
  • Loading branch information
netbonus and mrcnk authored Feb 4, 2025
1 parent f8e37dd commit 0b5e419
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docs-build-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
node-version: 20.x

- name: Install pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v4
with:
version: 8

Expand Down
1 change: 1 addition & 0 deletions e2e
Submodule e2e added at dcb9e6
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gridplus-sdk",
"version": "3.2.0",
"version": "3.3.0",
"type": "module",
"description": "SDK to interact with GridPlus Lattice1 device",
"scripts": {
Expand Down
24 changes: 24 additions & 0 deletions src/__test__/e2e/xpub.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* eslint-disable quotes */
import { question } from 'readline-sync';
import { fetchAddressesByDerivationPath, pair } from '../../api';
import { setupClient } from '../utils/setup';
import { LatticeGetAddressesFlag } from '../../protocol';

describe('XPUB', () => {
test('pair', async () => {
const isPaired = await setupClient();
if (!isPaired) {
const secret = question('Please enter the pairing secret: ');
console.log('secret', secret);
await pair(secret.toUpperCase());
}
});

test('fetch bitcoin xpub', async () => {
const xpub = await fetchAddressesByDerivationPath("44'/0'/0'", {
flag: LatticeGetAddressesFlag.secp256k1Xpub,
});
expect(xpub).toHaveLength(1);
expect(xpub[0].startsWith('xpub')).toBe(true);
});
});
9 changes: 5 additions & 4 deletions src/api/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
type FetchAddressesParams = {
n?: number;
startPathIndex?: number;
flag?: number;
};

export const fetchAddresses = async (overrides?: GetAddressesRequestParams) => {
Expand Down Expand Up @@ -195,11 +196,11 @@ export const fetchBip44ChangeAddresses = async ({

export async function fetchAddressesByDerivationPath(
path: string,
{ n = 1, startPathIndex = 0 }: FetchAddressesParams = {},
{ n = 1, startPathIndex = 0, flag }: FetchAddressesParams = {},
): Promise<string[]> {
const components = path.split('/').filter(Boolean);
const parsedPath = parseDerivationPathComponents(components);
const flag = getFlagFromPath(parsedPath);
const _flag = getFlagFromPath(parsedPath);
const wildcardIndex = components.findIndex((part) =>
part.toLowerCase().includes('x'),
);
Expand All @@ -208,7 +209,7 @@ export async function fetchAddressesByDerivationPath(
return queue((client) =>
client.getAddresses({
startPath: parsedPath,
flag,
flag: flag || _flag,
n,
}),
);
Expand All @@ -223,7 +224,7 @@ export async function fetchAddressesByDerivationPath(
const result = await queue((client) =>
client.getAddresses({
startPath: currentPath,
flag,
flag: flag || _flag,
n: 1,
}),
);
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const EXTERNAL = {
SECP256K1_PUB: LatticeGetAddressesFlag.secp256k1Pubkey,
ED25519_PUB: LatticeGetAddressesFlag.ed25519Pubkey,
BLS12_381_G1_PUB: LatticeGetAddressesFlag.bls12_381Pubkey,
SECP256K1_XPUB: LatticeGetAddressesFlag.secp256k1Xpub,
},
// Options for building general signing requests
SIGNING: {
Expand Down
13 changes: 10 additions & 3 deletions src/functions/getAddresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ export const encodeGetAddressesRequest = ({
(flag === LatticeGetAddressesFlag.ed25519Pubkey ||
flag === LatticeGetAddressesFlag.secp256k1Pubkey ||
flag === LatticeGetAddressesFlag.bls12_381Pubkey);
if (!isPubkeyOnly && !isValidAssetPath(startPath, fwConstants)) {
const isXpub = flag === LatticeGetAddressesFlag.secp256k1Xpub;
if (!isPubkeyOnly && !isXpub && !isValidAssetPath(startPath, fwConstants)) {
throw new Error(
'Derivation path or flag is not supported. Try updating Lattice firmware.',
);
Expand Down Expand Up @@ -191,13 +192,19 @@ export const decodeGetAddressesResponse = (
}
off += 65;
} else {
// Otherwise we are dealing with address strings
// Otherwise we are dealing with address strings or XPUB strings
const addrBytes = data.slice(off, off + ProtocolConstants.addrStrLen);
off += ProtocolConstants.addrStrLen;
// Return the UTF-8 representation
const len = addrBytes.indexOf(0); // First 0 is the null terminator
if (len > 0) {
addrs.push(addrBytes.slice(0, len).toString());
// Clean control characters from the string before adding to array
const cleanStr = addrBytes
.slice(0, len)
.toString()
// eslint-disable-next-line no-control-regex
.replace(/[\x00-\x1F\x7F-\x9F]/g, '');
addrs.push(cleanStr);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/protocol/latticeConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export enum LatticeGetAddressesFlag {
secp256k1Pubkey = 3,
ed25519Pubkey = 4,
bls12_381Pubkey = 5,
secp256k1Xpub = 6, // For Bitcoin XPUB
}

export enum LatticeSignSchema {
Expand Down

0 comments on commit 0b5e419

Please sign in to comment.