Skip to content

Latest commit

 

History

History
303 lines (221 loc) · 9.53 KB

MIGRATION.md

File metadata and controls

303 lines (221 loc) · 9.53 KB

Migration Guides

Stacks.js (>=5.x.x) → (7.x.x)

Breaking Changes

  • The @stacks/network package was removed. Similar functionality is now available in @stacks/transactions. Read more...

StacksNodeApi

The new StacksNodeApi class lets you interact with a Stacks node or API.

import { StacksNodeApi } from '@stacks/transactions';

const api = new StacksNodeApi();
await api.broadcastTx(txHex);

StacksNetwork to StacksNodeApi

Stacks network objects are now exported by the @stacks/common package. They are used to specify network settings for other functions and don't require instantiation (like the @stacks/network approach did).

import { STACKS_MAINNET } from '@stacks/transactions';

After importing the network object (e.g. STACKS_MAINNET here), you can use it in other functions like so:

// todo: update more functions, show example

For easing the transition, the functions which depended on the networking aspect of @stacks/network now accept an api parameter. The api parameter can be an instance of StacksNodeApi or any object containing a url and fetch property.

The following diffs show examples of how to migrate to the new pattern.

import { makeSTXTokenTransfer } from '@stacks/transactions';

- import { StacksTestnet } from '@stacks/network';
+ import { STACKS_TESTNET } from '@stacks/transactions';

const transaction = await makeSTXTokenTransfer({
  // ...
- network: new StacksTestnet(),
+ network: STACKS_TESTNET,
});

Note

String literal network names are still supported.

const transaction = await makeSTXTokenTransfer({
  // ...
- network: new StacksTestnet(),
+ network: 'testnet',
});

Note

Custom URLs and fetch functions are still supported via the api parameter.

const transaction = await makeSTXTokenTransfer({
  // ...
- network: new StacksTestnet({ url: "mynode-optional.com", fetchFn: myFetch }), // optional options
+ network: STACKS_TESTNET,
+ api: { url: "mynode-optional.com", fetch: myFetch } // optional params
});

Stacks.js (<=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...
  • To allow message signing on Ledger hardware wallets, we are changing the message signing prefix. Read more...
  • Post-conditions for NFTs were renamed to be more clear: Owns to DoesNotSend, DoesNotOwn to Sends.

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. To migrate, switch Buffer code to instead use Uint8Array. The following code segments are the equivalent calls using Uint8Array rather than Buffers and assuming imports from @stacks/commonimport { hexToBytes, bytesToHex, utf8ToBytes, bytesToUtf8, asciiToBytes, bytesToAscii, concatBytes } from "@stacks/common"

// old:
Buffer.from('stacks Ӿ'); // <Buffer 73 74 61 63 6b 73 20 d3 be>

// new:
utf8ToBytes('stacks Ӿ'); // Uint8Array(9) [ 115, 116, 97, 99, 107, 115, 32, 211, 190 ];
// old:
Buffer.from([115, 116, 97, 99, 107, 115, 32, 211, 190]).toString(); // 'stacks Ӿ'

// new:
bytesToUtf8(Uint8Array.from([115, 116, 97, 99, 107, 115, 32, 211, 190])); // 'stacks Ӿ'
// old:
Buffer.from('stacks $', 'ascii'); // <Buffer 73 74 61 63 6b 73 20 24>

// new:
asciiToBytes('stacks $'); // Uint8Array(8) [ 115, 116, 97, 99, 107, 115, 32, 36 ]
// old:
Buffer.from([115, 116, 97, 99, 107, 115, 32, 36]).toString('ascii'); // 'stacks $'

// new:
bytesToAscii(Uint8Array.from([115, 116, 97, 99, 107, 115, 32, 36])); // 'stacks $'
// old:
Buffer.from('deadbeef', 'hex'); // <Buffer de ad be ef>

// new:
hexToBytes('deadbeef'); // Uint8Array(4) [ 222, 173, 190, 239 ]
// old:
Buffer.from([222, 173, 190, 239]).toString('hex'); // 'deadbeef'

// new:
bytesToHex(Uint8Array.from([222, 173, 190, 239])); // 'deadbeef'

Message Signing Prefix

The message signing prefix was changed from Stacks Message Signing to Stacks Signed Message. The change relates to the functions verifyMessageSignature, encodeMessage, decodeMessage, and hashMessage. The verifyMessageSignature functions was updated to verify against both the old and the new prefix (for unhashed message-input). This will generate a different hash/signature from the same input compared to previous versions of Stacks.js. If you have previously stored messages/signatures and compare to freshly generated ones, the messages/signatures will not match to previously stored.


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

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

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

// 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

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

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

import { encryptContent, decryptContent } from 'blockstack';

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

Using @stacks/encryption or @stacks/auth

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);