deso-protocol
Client side typescript/javascript SDK for building web3 applications for the DeSo blockchain.
Installation
npm i deso-protocol
Configuration
import { configure } from 'deso-protocol';
configure({
// Here we indicate the permissions a user will be asked to approve when they
// log into your application. You may specify as many or as few permissions up
// front as you want. You may choose not to request any permissions up front
// and that's okay! Just remember that you will need to request them in your
// app progressively, and you can always request as many or as few as you want
// using the `requestPermissions` method described in the usage section.
//
// See more about the spending limit options object here
// https://docs.deso.org/for-developers/backend/blockchain-data/basics/data-types#transactionspendinglimitresponse
// And See an exhaustive list of transaction types here:
// https://github.com/deso-protocol/core/blob/a836e4d2e92f59f7570c7a00f82a3107ec80dd02/lib/network.go#L244
spendingLimitOptions: {
// NOTE: this value is in Deso nanos, so 1 Deso * 1e9
GlobalDESOLimit: 1 * 1e9 // 1 Deso
// Map of transaction type to the number of times this derived key is
// allowed to perform this operation on behalf of the owner public key
TransactionCountLimitMap: {
BASIC_TRANSFER: 2, // 2 basic transfer transactions are authorized
SUBMIT_POST: 4, // 4 submit post transactions are authorized
},
}
// Optional node uri. Sets the uri for the node that will be used for all
// subsequent requests. If not passed it will default to https://node.deso.org
nodeURI: 'https://mynode.com',
// Optional redirect URI. This is mostly useful for native mobile use cases.
// Most web applications will not want to use it. If provided, we do a full
// redirect to the identity domain and pass data via query params back to the
// provided uri.
redirectURI: 'https://mydomain.com/my-redirect-path',
// This will be associated with all of the derived keys that your application
// authorizes.
appName: 'My Cool App',
// this is optional, if not passed the default of 1500 will be used.
MinFeeRateNanosPerKB: 1000,
// THE FOLLOWING CONFIGURATIONS ARE ONLY NEEDED IN A REACT NATIVE CONTEXT
/**
* An optional storage provider. If not provided, we will assume we're running
* in a browser context and localStorage is available. In react native you must
* set a storage provider which is likely an async storage instance.
*/
storageProvider?: Storage | AsyncStorage;
/**
* An optional function that can be used to customize how the identity url is opened. For
* example, if you are using react native, you might want to use the WebBrowser
* API to open the url in a system browser window.
* @example
* ```ts
* identityPresenter: async (url) => {
* const result = await WebBrowser.openAuthSessionAsync(url);
* if (result.type === 'success') {
* identity.handleRedirectURI(result.url);
* }
* },
* ```
*/
identityPresenter?: (url: string) => void;
})
Usage
See our react examples repo
API
Identity: (logging in and out, creating new accounts, etc)
import { identity } from 'deso-protocol';
// Subscribe to identity state changes (user login/logout, permissions updated,
// etc). This is useful for binding your preferred framework's state management
// system to the identity instance's internal state. The function you provide to
// `subscribe` will be called anytime identity's internal state changes.
identity.subscribe((state) => {
// The event property is a string value that tells you what triggered the
// subscribe call. Useful for setting loading states or otherwise making
// decisions about how you want your app to react to identity state.
// You can see an exhaustive list of the events here: https://github.com/deso-protocol/deso-js/blob/4d91fd7a66debd2aa0b0b49c0ccb872c0c849d49/src/identity/types.ts#L225
const event = state.event;
// The current user object contains the user's current permissions
// (TransactionCountLimitMap). This value will be updated when the logged in
// user changes or when the permissions change for the current user. Read
// more about the transaction count limit map here
// https://docs.deso.org/for-developers/backend/blockchain-data/basics/data-types#transactionspendinglimitresponse
const currentUser = state.currentUser;
// A list of all users that a given user has logged in with (excluding
// currentUser). This is useful if you want to show a list of accounts and
// provide a way to switch accounts easily.
const alernateUsers = state.alternateUsers;
});
// Start a login flow
await identity.login();
// Start a logout flow
await identity.logout();
// Switch users (for apps that manage multiple accounts for a single user).
// NOTE: The publicKey here must be a user that has previously logged in.
await identity.setActiveUser(publicKey);
// Generate a jwt for making authenticated requests via `Authorization` http
// header.
await identity.jwt();
// Sign and submit a transaction. This is handled for you if you're using any
// of the provided transaction creation helpers. But you can also do this yourself
// if you have a more complex use case.
const tx = await axios.post('https://node.deso.org/api/v0/submit-post');
const submittedTx = await identity.signAndSubmit(tx);
// For some use cases, you might want to handle signing, submitting,
// and retrying yourself. Here's an example of handling each step of the process
// yourself.
const postTransaction = await axios.post(
'https://node.deso.org/api/v0/submit-post'
);
const signedTx = await identity.signTx(postTransaction.TransactionHex);
const submittedTx = await identity.submitTx(signedTx);
// Checking for permissions is straightforward. Here we check if our app can
// post on behalf of a user Read more about the transaction count limit map here
// https://docs.deso.org/for-developers/backend/blockchain-data/basics/data-types#transactionspendinglimitresponse and you can find an exhaustive list
// of available transaction types here: https://github.com/deso-protocol/core/blob/a836e4d2e92f59f7570c7a00f82a3107ec80dd02/lib/network.go#L244
// This returns a boolean value synchronously and should be used in a browser context to prevent issues with
// popup blockers.
const hasPermission = identity.hasPermissions({
TransactionCountLimitMap: {
SUBMIT_POST: 1,
},
});
// The same as `hasPermissions` but async because the storage provider might be AsyncStorage
// This would typically be used in a native mobile (react native) context.
const hasPermission = await identity.hasPermissionsAsync({
TransactionCountLimitMap: {
SUBMIT_POST: 1,
},
});
// Here we request approval for permissions from a user. This will present the
// user with the deso identity approve derived key UI.
if (!hasPermissions) {
await identity.requestPermissions({
TransactionCountLimitMap: {
SUBMIT_POST: 1,
},
});
}
// Encrypt plain text with the recipients public key. This can be subsequently
// decrypted using the recipient's private key.
const encryptedMessageHex = await identity.encryptMessage(
recipientPublicKeyBase58Check,
plaintextMsg
);
// Decrypt a message returned from any of the message endpoints of the deso
// backend messages api. If it is a group message you will need to fetch the
// groups the user is a member of and provide them. If it's known that the
// message is not a a group message you can pass an empty array for the groups
// parameter.
//
// See the api docs for sending and receiving messages here:
// https://docs.deso.org/deso-backend/api/messages-endpoints
//
// See the api docs for access groups here:
// https://docs.deso.org/deso-backend/api/access-group-endpoints
const decryptedMessagePlaintext = await identity.decryptMessage(
message,
accessGroups
);
Data: fetching data from a node
import { getUsersStateless, getPostsStateless } from 'deso-protocol';
const users = await getUsersStateless({
PublicKeysBase58Check: [key1, key2, ...rest],
});
const posts = await getPostsStateless({ NumToFetch: 20 });
See the backend api documentation for reference. See an exhaustive list of the available data fetching functions here.
Transactions: Writing data to the blockchain
The deso-protocol library will handle signing and submitting transactions for confirmation for you. All you need to do is construct them by providing the raw data.
import { submitPost } from 'deso-protocol';
const txInfo = await submitPost({
UpdaterPublicKeyBase58Check: currentUser.publicKey,
BodyObj: {
Body: 'My first post on DeSo!',
ImageURLs: [],
VideoURLs: [],
},
});
See the transaction construction api documentation for reference. See an exhaustive list of the available transaction construction functions here
React Native
See REACT-NATIVE.md
Contributing
Pull requests are welcome!
Setup
- Clone this repo
git clone ...
cd deso-js
Useful workflows
- Run the test suite
npm run test
- Link local changes into another project
# in the deso-js root directory run
npm run link
# navigate to your project's root
cd $your_project_root_dir
# create symlink in node_modules that points to your local copy of deso-protocol
npm link deso-protocol