Skip to content

Migration Guide: v2 to v3

This guide will help you migrate your existing applesauce v2 applications to v3. Applesauce v3 introduces several breaking changes that improve the API consistency and modernize the codebase, but require some code updates.

Overview of Major Changes

  • Async APIs: All signer and account methods now return Promises (no more synchronous APIs)
  • NIP-07 Updates: Removed getRelays method as it's no longer part of the NIP-07 specification
  • Relay Operations: publish and authenticate methods now return Promises instead of Observables
  • Factory Reorganization: Event operations have been reorganized into groups which breaks imports

1. Accounts & Signers Changes

Async API Migration

Major Change: All signer and account methods now return Promises instead of being synchronous. This is to help standardize the API and make it easier to wrap and extend the classes.

ts
import { SimpleSigner } from "applesauce-accounts";

// v2 - Synchronous API
const account = new SimpleSigner();
const pubkey = account.getPubkey(); // Returns string directly
const event = account.signEvent(draft); // Returns NostrEvent directly

// v3 - Async API
const account = new SimpleSigner();
const pubkey = await account.getPubkey(); // Returns Promise<string>
const event = await account.signEvent(draft); // Returns Promise<NostrEvent>

Removed getRelays Method

The getRelays method has been removed from all signers and accounts as it's no longer part of the NIP-07 specification:

ts
// v2 - This method existed
const relays = await account.getRelays(); // ❌ Removed in v3

New ExtensionAccount.fromExtension Method

A new static method has been added for creating extension accounts:

ts
// v3 - New static method
import { ExtensionAccount } from "applesauce-accounts";

const account = await ExtensionAccount.fromExtension(); // Creates account from window.nostr

Migration Steps

  1. Add await keywords to all account and signer method calls:
ts
// v2
const pubkey = account.getPubkey();
const encrypted = account.encrypt(pubkey, message);
const decrypted = account.decrypt(pubkey, encryptedMessage);
const signed = account.signEvent(draft);

// v3
const pubkey = await account.getPubkey();
const encrypted = await account.encrypt(pubkey, message);
const decrypted = await account.decrypt(pubkey, encryptedMessage);
const signed = await account.signEvent(draft);
  1. Remove getRelays usage:
ts
// v2 - Remove this
const relays = await account.getRelays();

2. Relay Changes

Promise-Based Publish Methods

Major Change: Relay publish methods now return Promises instead of Observables.

ts
import { lastValueFrom } from "rxjs";

// v2 - Observable-based
const response = await lastValueFrom(relay.publish(event));
const responses = await lastValueFrom(pool.publish(event, relays));

// v3 - Promise-based
const response = await relay.publish(event); // Returns Promise<PublishResponse>
const responses = await pool.publish(event, relays); // Returns Promise<PublishResponse[]>

Authentication Methods

Authentication methods also now return Promises:

ts
// v2 - Observable-based
const authResponse = await lastValueFrom(relay.authenticate(challenge));
const authResponse2 = await lastValueFrom(relay.auth(challenge));

// v3 - Promise-based
const authResponse = await relay.authenticate(challenge); // Returns Promise<PublishResponse>
const authResponse2 = await relay.auth(challenge); // Returns Promise<PublishResponse>

Removed Interfaces

The following interfaces have been removed:

  • IRelayState - Use the Relay class directly
  • Nip01Actions - Methods are now part of the Relay class

Migration Steps

  1. Remove lastValueFrom usage for publish methods:
ts
// v2
import { lastValueFrom } from "rxjs";
const response = await lastValueFrom(relay.publish(event));

// v3
const response = await relay.publish(event);
  1. Update authentication calls:
ts
// v2
const authResponse = await lastValueFrom(relay.authenticate(challenge));

// v3
const authResponse = await relay.authenticate(challenge);

3. Factory & Operations Changes

Reorganized Exports

Major Change: Event operations have been reorganized and all exports have been renamed.

Import groups of operations instead of individual methods

Most of the operations have been moved into groups to make it easier to import and use them.

ts
// v2
import { setListTitle, setListImage, setListDescription } from "applesauce-factory/operations";

await factory.build(
  { kind: 30000 },
  setListTitle("new list"),
  setListImage("https://example.com/image.png"),
  setListDescription("This is a new list"),
);

// v3 - Use new names
import { List } from "applesauce-factory/operations";

await factory.build(
  { kind: 30000 },
  List.setTitle("new list"),
  List.setImage("https://example.com/image.png"),
  List.setDescription("This is a new list"),
);

Summary of Required Changes

Breaking Changes (Must Update)

  1. Add await to all account/signer method calls - they now return Promises
  2. Remove getRelays() usage on signers and accounts - method no longer exists
  3. Update relay publish calls - remove lastValueFrom() wrapper since it returns a promise
  4. Update relay authentication calls - remove lastValueFrom() wrapper since it returns a promise
  1. Use new ExtensionAccount.fromExtension() static method for creating extension accounts