@soulbind/sdk
TypeScript icon, indicating that this package has built-in type declarations

0.5.1 • Public • Published

Soulbind SDK

A complete soulbound token solution in JavaScript (and TypeScript).

Platform

Want to see what's possible? Check out the site we built with this SDK: mainnet or testnet

Installation

Using NPM

npm i @soulbind/sdk

Usage

Import

import Soulbind from '@soulbind/sdk';

Invoke

...

const soulbind = new Soulbind({
    apiKey: 'YourApiKeyHere',
    // testnet: true, // Use this in your dev/test environments.
});

const { success } = await soulbind.getTokens('0xab5801a7d398351b8be11c439e05c5b3259aec9b');
console.log(success);
// Output: TokenData[]

Table of Contents

Features

Burn Authorization

This allows you to set a token Burn Auth. Or in other words, after a token has been claimed, this will determine who has the right to burn/delete that token.

Options: Issuer (you), Claimer, Both, Neither.

Restricted

Toggling this on allows you to pre-issue tokens to wallet AND/OR email addresses.

Data on who has claimed a token can be surfaced via our Core Methods or within the Soulbind Token Management page (mainnet / testnet).

Transferable (until bound)

Toggling this on will allow a token to be transferred until bound. After a user claims this token, they will have the ability to transfer this token at will. Users who own this token can choose to "Soulbind" it, preventing it from being transferred further.

Data on who has bound (or not bound) a token can be surfaced via our Core Methods or within the Soulbind Token Management page (mainnet / testnet).

In our data structures, you will see this represented as BoE (Bind on Equip).

Updatable

Creating a token with updatable functionality allows you to update an individual token's metadata at a later date. Once a token has been claimed, you can update that token to reflect new data at any time.

Methods

Email

These methods are used to seamlessly onboard users via email. Perfect for, but not limited to, non-web3 native users.

emailConnect

emailConnect(): string

Connects (or re-connects) a user via email address. For first-time connection, a UI will be displayed that walks the user through the process. Subsequent attempts to this call will re-connect the user without the UI process.

const address = await soulbind.emailConnect();
console.log(address);
// Output: 0xab5801a7d398351b8be11c439e05c5b3259aec9b

emailDisconnect

emailDisconnect(): string

Disconnects an email user.

await soulbind.emailDisconnect();

getEmailSignature

getEmailSignature(): Promise<string>

Gets a signature hash that can be passed to Soulbind txn methods. i.e. claim

const signature = await soulbind.getEmailSignature();
console.log(signature);
// Output: EVM signature for the connected address.

getEmailWalletAddress

getEmailWalletAddress(): string

Returns the currently connected email wallet address.

const address = soulbind.getEmailWalletAddress();
console.log(address);
// Output: 0xab5801a7d398351b8be11c439e05c5b3259aec9b

Core

These are the core methods for your soulbound tokens.

addToIssued

addToIssued(eventId, AddToIssuedRequest, AuthorizationRequest): Promise<ApiResponse<string[]>>

Issues more tokens or unique codes. Accepts address whitelist, unique codes, or both.

const authorizedAddress = await signer.getAddress();
const authorizedMessage = soulbind.getSignatureMessage(authorizedAddress);
const authorizersSignature = await signer.signMessage(authorizedMessage);

const data = {
  addresses: [
    '0xA1d04574E852cB814465E19220d06d04cDb272af',
    '0x3C229411128107734DCEA2c0b2Bd3B47755Fce16',
  ],
  codeCount: 5, // Generates 5 more unique codes.
};

const { success } = await soulbind.addToIssued('EventIdHere', data, {
  signature: authorizersSignature,
  message: authorizedMessage,
});
console.log(success);
// Output: 'txnHash'

bind

bind(eventId, tokenId, address, signature, message): Promise<ApiResponse<boolean>>

Bind SBT. Only useable on BoE tokens.

const receiverAddress = await signer.getAddress();
const message = soulbind.getSignatureMessage(address);
const receiverSignature = await signer.signMessage(message);

const { success } = await soulbind.bind(
  'EventIdHere',
  'TokenIdHere',
  receiverAddress,
  receiverSignature,
  message
);
console.log(success);
// Output: true

burn

burn(eventId, tokenId, address, signature, message): Promise<ApiResponse<boolean>>

Burn a token for a given wallet address.

const receiverAddress = await signer.getAddress();
const message = soulbind.getSignatureMessage(address);
const receiverSignature = await signer.signMessage(message);

const { success } = await soulbind.burn(
  'EventIdHere',
  'TokenIdHere',
  receiverAddress,
  receiverSignature,
  message
);
console.log(success);
// Output: true

claim

claim(eventId, address, signature, message, uniqueCode?): Promise<ApiResponse<boolean>>

Mint SBT to given address.

const receiverAddress = await signer.getAddress();
const message = soulbind.getSignatureMessage(address);
const receiverSignature = await signer.signMessage(message);

const { success } = await soulbind.claim(
  'EventIdHere',
  receiverAddress,
  receiverSignature,
  message
);
console.log(success);
// Output: tokenId

drop

drop(eventId, dropTo, AuthorizationRequest): Promise<ApiResponse<string[]>>

Drops a token to any number of addresses. This functions like a bulk claim that does not require receiver interaction.

NOTE: Only works with tokens that have BurnAuth.OwnerOnly OR BurnAuth.Both.

const authorizedAddress = await signer.getAddress();
const authorizedMessage = soulbind.getSignatureMessage(authorizedAddress);
const authorizersSignature = await signer.signMessage(authorizedMessage);

const dropTo = [
  '0xA1d04574E852cB814465E19220d06d04cDb272af',
  '0x3C229411128107734DCEA2c0b2Bd3B47755Fce16',
];
const { success } = await soulbind.drop('EventIdHere', dropTo, {
  signature: authorizersSignature,
  message: authorizedMessage,
});
console.log(success);
// Output: ['txnHash', 'txnHash']

create

createFile(FileUploadRequest) createToken(data: CreateRequest)

Token creation is a 2-step process that involves uploading a token image and its metadata to IPFS and then creating a Token on the Soulbind protocol.

NOTE: This is in development. In the interim, use: Soulbind Create Page (mainnet / testnet)

getAccountTokens

getAccountTokens(): Promise<ApiResponse<TokenData[]>>

Get SBT events that your organization has created.

const { success } = await soulbind.getAccountTokens();
console.log(success);
// Output: TokenData[]

getAccountTokensFiltered

NOTE: Used for specific account token queries or multi-tennant accounts. For a simpler query, use: getAccountTokens()

getAccountTokensFiltered(address, signature, message): Promise<ApiResponse<TokenData>>

Get SBT events that your address or other tenant that you are authorized to use has created.

const creatorsAddress = await signer.getAddress();
const creatorsSignature = await signer.signMessage(soulbind.getSignatureMessage(address));

const { success } = await soulbind.getAccountTokensFiltered(creatorsAddress, creatorsSignature);
console.log(success);
// Output: TokenData[]

getCreatedToken

getCreatedToken(eventId, tokenId?): Promise<ApiResponse<TokenData>>

Get a created SBT - use when you need the most current TokenData directly from chain. Pass in tokenId to populate the issuedTo property with token owner data.

const eventId = 'EventIdHere';
const optionalTokenId = 'TokenIdHere';

const { success } = await soulbind.getCreatedToken(eventId, optionalTokenId);
console.log(success);
// Output: TokenData

getSignatureMessage

NOTE: required with most txn

getSignatureMessage(address): string

Construct a formatted message to be signed by user and passed to Soulbind txn methods.

  // Specific signature message used below
  const signatureMessage = soulbind.getSignatureMessage(address);

  // This example uses ethers.js to get a signer - use w/e method you currently have to get a signer.
  const provider = new ethers.providers.Web3Provider(window.ethereum);
  const signer = provider.getSigner();
  const address = await signer.getAddress();

  // Using your signer, get the user to sign the signatureMessage from above.
  const signature = await signer.signMessage(signatureMessage);

  // Pass signature to Soulbind txn methods
  ...

getTokens

getTokens(address, filter?): Promise<ApiResponse<TokenData[]>>

Get all SBTs for an address. For filter options see: FilterType.

const { success } = await soulbind.getTokens('0xab5801a7d398351b8be11c439e05c5b3259aec9b');
console.log(success);
// Output: TokenData[]

increaseTokenLimit

increaseTokenLimit(eventId, limitIncrease, AuthorizationRequest): Promise<ApiResponse<string[]>>

Increase token limit of a non-restricted token.

const authorizedAddress = await signer.getAddress();
const authorizedMessage = soulbind.getSignatureMessage(authorizedAddress);
const authorizersSignature = await signer.signMessage(authorizedMessage);

const limitIncrease = 5;

const { success } = await soulbind.increaseTokenLimit('EventIdHere', limitIncrease, {
  signature: authorizersSignature,
  message: authorizedMessage,
});
console.log(success);
// Output: 'txnHash'

update

update(updateRequest: UpdateRequest): Promise<ApiResponse<string>>

Update a single token. Returns the update txn hash.

const message = soulbind.getSignatureMessage(address);
const issuersAddress = await signer.getAddress();
const IssuersSignature = await signer.signMessage(message);

const newMetadata = {
  name: 'Awesome blossom',
  description: 'This token represents your level.',
  external_url: 'https://soulbind.app',
  attributes: [
    {
      trait_type: 'Level',
      value: '2',
    },
  ],
};

const updateRequest = {
  address: issuersAddress,
  eventId: 'EventIdHere',
  message,
  metaData: newMetadata,
  signature: IssuersSignature,
  tokenId: 'TokenIdHere', // ID of the token you will be updating.
  tokenUri: 'TokenUriHere',
};

const { success } = await soulbind.update(updateRequest);
console.log(success);
// Output: txnHash

validateClaimAuthAddress

validateClaimAuthAddress(eventId, address): Promise<ApiResponse<boolean>>

Validate if an address has rights to claim a token.

const eventId = 'EventIdHere';
const address = 'AddressHere';

const { success } = await soulbind.validateClaimAuthAddress(eventId, address);
console.log(success);
// Output: true

validateClaimAuthCode

validateClaimAuthCode(eventId: string, code: string): Promise<ApiResponse<boolean>>

Validate if a unique code has rights to claim a token.

const eventId = 'EventIdHere';
const code = 'CodeHere';

const { success } = await soulbind.validateClaimAuthCode(eventId, code);
console.log(success);
// Output: true

validateClaimedToken

validateClaimedToken(eventId, address, bound?): Promise<ApiResponse<boolean>>

Validate that an address has claimed a token.

const eventId = 'EventIdHere';
const address = 'AddressHere';
const isTokenBound = true; // optional - use if your event is BOE and you want to validate that a token is soulbound.

const { success } = await soulbind.validateClaimedToken(eventId, address, isTokenBound);
console.log(success);
// Output: true/false

Models

AddToIssuedRequest

interface AddToIssuedRequest {
  addresses?: string[]; // (optional) Array of addresses to add to whitelist.
  codeCount?: number; // (optional) Number representing how many unique codes to generate.
}

AuthorizationRequest

interface AuthorizationRequest {
  signature: string;
  message: string;
}

ApiResponse

interface ApiResponse<T> {
  errorCode?: ErrorCode;
  success?: T;
}

Reference: ErrorCode

BurnAuth

enum BurnAuth {
  IssuerOnly,
  OwnerOnly,
  Both,
  Neither
}

ClaimStatus

enum ClaimStatus {
  issued,
  claimed,
  emailed,
  burned
}

CreateRequest

interface CreateRequest {
  address: string;
  boe: boolean;
  burnAuth: BurnAuth;
  metaData: SbtMetadata;
  restricted: boolean;
  signature: string;
  tokenUri: string; // must be in the format: 'ipfs://<CID>/metadata.json'
  // restricted = false
  tokenLimit?: number;
  // restricted = true
  issuedToCodes?: Token[];
  issuedToWalletAddresses?: Token[];
}

Reference: BurnAuth, SbtMetadata, Token

UpdateRequest

interface UpdateRequest {
  address: string;
  eventId: string;
  message: string;
  metaData: SbtMetadata;
  signature: string;
  tokenId: string;
  tokenUri: string; // must be in the format: 'ipfs://<CID>/metadata.json'
}

ErrorCode

enum ErrorCode {
  entityExists = 'Entity already exists',
  entityDoesntExist = 'Entity does NOT exists',
  invalidRequest = 'Invalid request',
  unauthorized = 'Unauthorized',
}

FileUploadRequest

interface FileUploadRequest extends SbtMetadata {
  file: File; // js native file object
}

Reference: SbtMetadata, File

FilterType

interface FilterType {
  organization?: boolean; // return user owned tokens that your org has created.
  canClaim?: boolean; // return restricted tokens that have been issued but not claimed by the user.
}

Reference: ClaimStatus, SbtMetadata

SbtMetadata

interface SbtMetadata {
  description: string;
  external_url: string;
  image: string; // IPFS URI or Backend Image data
  name: string;
  attributes: TokenAttributes[];
}

Reference: TokenAttributes

Tenant

interface Tenant {
  id: string;
  name: string;
}

Token

interface Token {
  created: number;
  eventId: string; // id of the EventToken
  status: ClaimStatus;
  to: string; // email address, wallet address, or code
  bound?: boolean; // true or false, only if eventtoken is BOE
  claimersEmail?: string; // added after a uniqueCode claim to retain email addresses
  code?: string; // secret code
  metaData?: SbtMetadata; // If token was updated, its data will display here.
  tenantId?: string; // Id of Tenant
  tokenId?: number | undefined; // On-chain token ID - not available for un-claimed issued tokens
  txnHash?: string; // Hash of the transaction that minted the token
}

TokenAttributes

interface TokenAttributes {
  trait_type: string;
  value: string | number;
}

TokenData

This is the main object within the Soulbind ecosystem. When you create a token (see create() or our create page mainnet / testnet) the Soulbind contract generates this object based on the data received. When users claim this token, data about that claim will be added to the issuedTo array. This includes who claimed the token in the form of a wallet address and the token's on-chain ID (tokenId).

interface TokenData {
  boe: boolean; // Bind on equip. Makes the token an NFT (true) or SBT (false)
  burnAuth: BurnAuth;
  count: number;
  contract: string; // The contract that this token was minted on - for backwards compatability
  created: number;
  id: string; // eventId
  idHash: string; // hash of eventId
  issuedTo: Token[]; // Individual claimed/issued tokens
  limit: number;
  metaData: SbtMetadata;
  owner: string; // issuer wallet address
  tenant: Tenant;
  restricted: boolean; // Pre-issued tokens = true
  txnHash: string; // Hash of the create transaction
}

Reference: BurnAuth, SbtMetadata, Tenant, Token

Package Sidebar

Install

npm i @soulbind/sdk

Weekly Downloads

0

Version

0.5.1

License

GPL-3.0

Unpacked Size

87.6 kB

Total Files

13

Last publish

Collaborators

  • chonknorris
  • andrew-c