Skip to content

Commit

Permalink
feat!: switch from buffer to uint8array (#1343)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
Removes compatibility with `bip32` package from @stacks/wallet-sdk. Now all derivation methods only rely on HDKey from @scure/bip32.

BREAKING CHANGE:
To reduce the bundle sizes of applications using Stacks.js we are moving away from Buffer (a polyfill to match Node.js APIs) to Uint8Arrays (which Buffers use in the background anyway). To make the switch easier we have introduced a variety of methods for converting between strings and Uint8Arrays: `hexToBytes`, `bytesToHex`, `utf8ToBytes`, `bytesToUtf8`, `asciiToBytes`, `bytesToAscii`, and `concatBytes`.

Co-authored-by: janniks <janniks@users.noreply.github.com>
  • Loading branch information
janniks and janniks committed Sep 30, 2022
1 parent fcb69af commit 5445b73
Show file tree
Hide file tree
Showing 145 changed files with 4,167 additions and 10,639 deletions.
2 changes: 0 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ module.exports = {
'@typescript-eslint/no-unsafe-member-access': [0],
'@typescript-eslint/no-non-null-assertion': [0],

'node/prefer-global/buffer': ['error', 'never'],

'import/no-extraneous-dependencies': ['error'],
},
};
18 changes: 18 additions & 0 deletions .github/DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Adding dependencies

This repo uses Lerna [hoisting](https://github.com/lerna/lerna/blob/main/doc/hoist.md) for package dependencies.

In order to install a new dependency to a package, the [`lerna add`](https://github.com/lerna/lerna/tree/main/commands/add) command must be used, rather than `npm install <package>`.

For example, the following command installs `lodash` as a dependency to the `@stacks/storage` package:

```shell
# Run within the root directory
npx lerna add lodash --scope @stacks/storage
```

Add `--dev` to install as a development dependency:

```shell
npx lerna add lodash --scope @stacks/storage --dev
```
194 changes: 194 additions & 0 deletions .github/MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Migration Guides

- [Stacks.js (&lt;=4.x.x) → (5.x.x)](#stacksjs-4xx--5xx)
- [Breaking Changes](#breaking-changes)
- [Buffer to Uint8Array](#buffer-to-uint8array)
- [blockstack.js → Stacks.js (1.x.x)](#blockstackjs--stacksjs-1xx)
- [Auth](#auth)
- [Using blockstack.js](#using-blockstackjs)
- [Using Blockstack Connect](#using-blockstack-connect)
- [Storage](#storage)
- [Using blockstack.js](#using-blockstackjs-1)
- [Using @stacks/storage](#using-stacksstorage)
- [Encryption](#encryption)
- [Using blockstack.js](#using-blockstackjs-2)
- [Using @stacks/encryption or @stacks/auth](#using-stacksencryption-or-stacksauth)

## Stacks.js (&lt;=4.x.x) → (5.x.x)

### Breaking Changes

- To reduce the bundle sizes of applications using Stacks.js we are switching from Buffer (a polyfill to match Node.js APIs) to Uint8Arrays (which Buffers use in the background anyway). [Read more...](#buffer-to-uint8array)

#### Buffer to Uint8Array

To make the switch easier we have introduced a bunch of methods for converting between strings and Uint8Arrays: `hexToBytes`, `bytesToHex`, `utf8ToBytes`, `bytesToUtf8`, `asciiToBytes`, `bytesToAscii`, and `concatBytes`.
The following code segments are the equivalent calls using Uint8Array rather than Buffers and assuming imports from `@stacks/common``import { hexToBytes, bytesToHex, utf8ToBytes, bytesToUtf8, asciiToBytes, bytesToAscii, concatBytes } from "@stacks/common"`

```ts
Buffer.from('stacks Ӿ'); // <Buffer 73 74 61 63 6b 73 20 d3 be>
utf8ToBytes('stacks Ӿ'); // Uint8Array(9) [ 115, 116, 97, 99, 107, 115, 32, 211, 190 ];
```

```ts
Buffer.from([115, 116, 97, 99, 107, 115, 32, 211, 190]).toString(); // 'stacks Ӿ'
bytesToUtf8(Uint8Array.from([115, 116, 97, 99, 107, 115, 32, 211, 190])); // 'stacks Ӿ'
```

```ts
Buffer.from('stacks $', 'ascii'); // <Buffer 73 74 61 63 6b 73 20 24>
asciiToBytes('stacks $'); // Uint8Array(8) [ 115, 116, 97, 99, 107, 115, 32, 36 ]
```

```ts
Buffer.from([115, 116, 97, 99, 107, 115, 32, 36]).toString('ascii'); // 'stacks $'
bytesToAscii(Uint8Array.from([115, 116, 97, 99, 107, 115, 32, 36])); // 'stacks $'
```

```ts
Buffer.from('deadbeef', 'hex'); // <Buffer de ad be ef>
hexToBytes('deadbeef'); // Uint8Array(4) [ 222, 173, 190, 239 ]
```

```ts
Buffer.from([222, 173, 190, 239]).toString('hex'); // 'deadbeef'
bytesToHex(Uint8Array.from([222, 173, 190, 239])); // 'deadbeef'
```

---

## blockstack.js → Stacks.js (1.x.x)

This guide will help migrate your Blockstack app from blockstack.js to the new Stacks.js packages and Connect.

### Auth <!-- omit from toc -->

The main change for auth is that the Stacks Connect library has replaced the `redirectToSignIn` function from blockstack.js.
Instead of redirecting to the now deprecated Blockstack Browser, the authentication flow is completed within a popup window using
the new authenticator app.
You can still use the API in `@stacks/auth` to create custom auth requests manually if desired.

### Using blockstack.js

```typescript
import { UserSession, AppConfig } from 'blockstack';

// Configuring your app
const appConfig = new AppConfig();
const userSession = new UserSession({ appConfig });

// Initiating auth flow
if (!userSession.isUserSignedIn()) {
userSession.redirectToSignIn();
}

// Handling sign in
if (userSession.isSignInPending()) {
userSession.handlePendingSignIn().then(userData => {
window.history.replaceState({}, document.title, '/');
this.setState({ userData: userData });
});
}
```

#### Using Blockstack Connect

See full tutorial [here](https://docs.blockstack.org/authentication/connect)

```typescript
// Configuring your app
const authOptions = {
redirectTo: '/',
finished: ({ userSession }) => {
console.log(userSession.loadUserData());
},
appDetails: {
name: 'My Cool App',
icon: 'https://example.com/icon.png',
},
};

import { showBlockstackConnect } from '@stacks/connect';
import { UserSession, AppConfig } from '@stacks/auth';
import { Connect } from '@stacks/connect';

// Initiating auth flow - using the Connect component
const App = () => <Connect authOptions={authOptions}>// the rest of your app's components</Connect>;
// Initiating auth flow - alternatively
showBlockstackConnect(authOptions);

// Handling sign in
const appConfig = new AppConfig();
const userSession = new UserSession({ appConfig });

// ... call this code on page load
if (userSession.isSignInPending()) {
const userData = await userSession.handlePendingSignIn();
// your user is now logged in.
}
```

### Storage

In Stacks.js, storage is now a separate package.

#### Using blockstack.js

```typescript
import { UserSession, AppConfig } from 'blockstack';

const appConfig = new AppConfig();
const userSession = new UserSession({ appConfig });

userSession.putFile('my_file.json', my_content);
userSession.getFile('my_file.json').then(file => {});
```

#### Using @stacks/storage

```typescript
import { UserSession } from '@stacks/auth';
import { Storage } from '@stacks/storage';

const appConfig = new AppConfig();
const userSession = new UserSession({ appConfig });
const storage = new Storage({userSession});

storage.putFile('my_file.json', my_content));
storage.getFile('my_file.json').then((file) => {

});

```

### Encryption

Encryption/Decryption functions have been moved into a separate `@stacks/encryption` library.

#### Using blockstack.js

```typescript
import { encryptContent, decryptContent } from 'blockstack';

encryptContent(userSession, content, options);
decryptContent(userSession, encryptedContent, options);
```

#### Using @stacks/encryption or @stacks/auth

```typescript
import { encryptContent, decryptContent } from '@stacks/encryption';
import { UserSession } from '@stacks/auth';

encryptContent(content, { privateKey });
decryptContent(encryptedContent, { privateKey });

// Using userSession
const appConfig = new AppConfig();
const userSession = new UserSession({ appConfig });
const storage = new Storage(userSession);

userSession.encryptContent(content);
userSession.decryptContent(encryptedContent);
```
134 changes: 0 additions & 134 deletions .github/MIGRATION_GUIDE.md

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ jobs:
run: echo "::set-output name=version::$(cat lerna.json | jq -r '.version')"
- uses: kyranjamie/pull-request-fixed-header@v1.0.1
with:
header: "> This PR was published as an *alpha* to npm with the version `${{ steps.published-version.outputs.version }}`e.g. `npm install @stacks/common@${{ steps.published-version.outputs.version }}`"
header: "> This PR was published to npm with the version `${{ steps.published-version.outputs.version }}`\n> e.g. `npm install @stacks/common@${{ steps.published-version.outputs.version }} --save-exact`"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8 changes: 8 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"esbenp.prettier-vscode",
"yzhang.markdown-all-in-one"
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"markdown.extension.toc.levels": "2..6"
}

0 comments on commit 5445b73

Please sign in to comment.