xmtp / xmtp-js

XMTP client SDKs, content types, and other packages written in TypeScript
https://xmtp.org/docs
217 stars 42 forks source link

v11 Release #458

Closed neekolas closed 1 year ago

neekolas commented 1 year ago

Summary

xmtp-js v11 release

New features

Improved server-side performance

If you’re a Node.js developer, this is the release you’ve been waiting for.

We’ve added key extensibility points to the SDK enabling you to replace components designed for the browser with higher-performance options specifically designed to work in Node.js.

****Pluggable GRPC API client****

By default, xmtp-js uses the HttpApiClient to connect to the XMTP network over HTTP using Fetch. Using this default API client can be expensive and isn’t well-designed for long-lived streaming sessions. Because the XMTP web API doesn’t support bidirectional streaming, any time you need to update the content topics in a stream (for example, every time a new conversation is started in streamAllMessages) the default API client needs to disconnect and reconnect the stream. This behaviour can cause missed messages, especially in cases of high-traffic bots with many ongoing conversations.

With xmtp-js v11, you can now use a new package @xmtp/grpc-api-client to replace the default API client. This new client offers faster encoding/decoding by using protobuf and GRPC directly. The client also supports bidirectional streams over GRPC.

To take advantage of this pluggable GRPC API client, just instantiate your client with an apiClientFactory specified.

import { Client } from '@xmtp/xmtp-js'
import { GrpcApiClient } from '@xmtp/grpc-api-client'

const client = await Client.create(someWallet, { 
    apiClientFactory: GrpcApiClient.fromOptions
})

This will not work in the browser.

The GRPC API Client is currently in alpha status and is not yet ready to be used in production applications. Follow this issue for more details.

****Pluggable persistence****

Conversation caching in xmtp-js was initially designed for the browser, reliant on the LocalStorage API. In Node.js, caching wasn’t persistent and was started fresh every time you created a client.

You can now use a pluggable engine for the base persistence layer, enabling you to drop in something more suitable for your server-side environment.

import { Client } from '@xmtp/xmtp-js'

const client = await Client.create(someWallet, {
    basePersistence: new MyCustomPersistence()
})

We’ve created a few reference implementations of our Persistence interface that you can drop in. For example, take a look at @xmtp/redis-persistence and @xmtp/fs-persistence in the experimental new Bot Kit Pro repo.

More robust conversation caching

Conversation caching only worked for XMTP V2 conversations. While these are the vast majority of conversations on the network, some long-time users have many V1 conversations that need to be refreshed every time the client is instantiated. The conversation caching system has been overhauled to be more reliable and to support both V1 and V2 conversations.

MetaMask Snaps support

With the public release of MetaMask Snaps, developers can finally start experimenting with supporting the “Sign in with XMTP” Snap.

This Snap offers a more secure and simpler sign-in experience. If a user has signed in to any app built with XMTP using this Snap, you won’t need to prompt for signatures when they sign in to your app.

This removes the need for Client.getKeys() for any user who has the “Sign in with XMTP” Snap enabled. You can persist their sign-in session for 30 days in the Snap without ever having to touch the user’s XMTP keys. Even after 30 days, no new signatures are required.

To enable the Snap in your browser-based app, just set the useSnaps flag to true as part of client creation.

Typed message content

A frequent source of bugs in apps built with XMTP is mishandling custom content types. The SDKs were definitely part of the problem since they return message.content as an any type. The same is true of conversation.send(...), where the message argument is an any type.

v11 adds support for inferring message content types based on the list of codecs provided as part of client instantiation. None of the errors underlined in red below would have surfaced without this support in place.

xmtp js code sample with strong typing

If no custom codecs are provided, the possible types for message content are string | undefined.

Upgrade from v10 to v11

Take advantage of typed message content

Typed message content is opt-in, unless it can automatically be inferred.

For simple examples like the one above—cases where you are creating a Client and using it directly—everything should work out of the box. Things get a little trickier as you pass types around in your app. Consider the following React component:

import React from 'react'
import { DecodedMessage, Client } from '@xmtp/xmtp-js'

type Props = {
  message: DecodedMessage
}

export const MyComponent = ({ message }: Props) => {
  // message.content will be an any type here
  return <span>{message.content}</span>
}

Because the Props are explicitly typed as DecodedMessage, which defaults to DecodedMessage<any>, you won’t see the benefits of a typed client here. You can update the Props to fix this:

type Props = {
    message: DecodedMessage<string>
}

The same applies to instances of Client and Conversation as well.

The default generic type for Client, Conversation, and DecodedMessage will become unknown in a future major version release, so this is a good time to start making your content types explicit.

Breaking changes

Fallbacks are now handled by the codecs directly. The fallbackText field has been removed from SendOptions.

Upgrade tasks

cloudflare-workers-and-pages[bot] commented 1 year ago

Deploying with  Cloudflare Pages  Cloudflare Pages

Latest commit: 73818d8
Status: ✅  Deploy successful!
Preview URL: https://e82070b5.xmtp-js.pages.dev
Branch Preview URL: https://beta.xmtp-js.pages.dev

View logs