Code Repo
https://github.com/SphereGlobal/WebSDK
Supported Platforms
- React (can be used for both ReactJs and NextJs also)
Installing the SDK
At present, the SphereOne WebSDK is not available through the NodePackage Manager (NPM) as a standard Node Package.
Developers are required to employ an alternative installation method by directly utilizing Node. This involves specifying both the SphereOne's GitHub organization and the library name during the installation process.
npm install github:SphereGlobal/WebSDK#main
Or yarn
:
yarn add github:SphereGlobal/WebSDK#main
Getting Latest Updates
To get the latest updates from the SDK, developers would need to manually run the installation command again:
npm install github:SphereGlobal/WebSDK#main
This should pull the latest changes and update the .lock
file.
Initializing the SDK
To initialize the WebSDK in a new project or existing project, we need to import and instantiate the WebSDK.
import WebSDK, { LoginBehavior } from "websdk";
const clientId = "your-client-id";
const redirectUri = "your-website-redirect-uri";
const apiKey = "your-merchant-api-key";
export const sphereoneSdk = new WebSDK(clientId, redirectUri, apiKey, LoginBehavior.REDIRECT);
To obtain many of the values essential for initializing the WebSDK, please engage in communication with SphereOne to secure the accurate values.
Key Values for WebSDK Initialization:
your-client-id
- This value is indispensable for SphereOne to authenticate that the invoker is associated with a specific client.setLoginType
- This value is crucial to determine the nature of the login experience. SphereOne recommends setting this value toREDIRECT
.your-merchant-api-key
- This key is vital for certain WebSDK API calls, serving to identify the invoker as a legitimate merchant within SphereOne's system.your-website-redirect-url
- This URL is essential for the login process to discern where to dispatch the authentication response back.
Login
After initializing the WebSDK, to login the user, developer can call the WebSDK method: login()
import { sphereoneSdk } from "./your-implementation-file";
// login function for button onClick
const login = async () => {
try {
await sphereoneSdk.login();
} catch (e: any) {
console.error(e);
}
};
This will trigger the login functionality with the WebSDK. It will redirect user to SphereOne's login screen, and user can proceed from there, with similar experience as SphereOne's applications.
To listen and get the response back from the authentication and also know if user is signed in or not:
// something to track user's sign-in state with SphereOne on client-side
const [isLoggedIn, setIsLoggedIn] = useState(false);
// hook to listen for authentication response
useEffect(() => {
const handleAuth = async () => {
const authResult: any = await sphereoneSdk.handleCallback();
if (authResult.access_token) {
const { access_token, profile } = authResult;
setIsLoggedIn(true); // handle authentication with your database
} else {
setIsLoggedIn(false);
}
};
handleAuth();
}, []);
The WebSDK will internally store and keep track of the accessToken
returned from the authentication. So, there's no need for developers to explicitly store the accessToken
.
But if developer wants to use the accessToken
for making a SphereOne API call that's not within the SDK, then there are getter methods in the SDK to get the accessToken
and IdToken
.
// `getAccessToken` and `getIdToken` will return an empty string if user is not logged in.
const accessToken:string = sphereoneSdk.getAccessToken();
const idToken:string = sphereoneSdk.getIdToken();
Get User Data
Once user is successfully signed in, all user information, wallets, and their balances will be loaded into the SDK.
To get user info, developer can call the WebSDK method: getUserInfo()
const getUserInfo = async () => {
const userInfo = await sphereoneSdk.getUserInfo({ forceRefresh: false });
console.log("userInfo", JSON.stringify(userInfo));
};
The example simply prints out the userInfo
of the current signed-in user to the console.
If developers want to pull latest updates for user wallets, they can utilize the same call as above and pass { forceRefresh: true }
as a parameter.
If { forceRefresh: true }
is not passed, then what's returned by getUserInfo will be what's currently stored/cached in the WebSDK.
const getUserInfo = async (refresh: boolean) => {
const userInfo = await sphereoneSdk.getUserInfo({ forceRefresh: refresh });
console.log("userInfo", JSON.stringify(userInfo));
};
Get User Wallets
To get user wallets, developer can call the WebSDK method: getWallets()
const getUserWallets = async () => {
const userWallets = await sphereoneSdk.getWallets({ forceRefresh: false });
console.log("userWallets", JSON.stringify(userWallets));
}
This method follows similarly to the getUserInfo
example above.
Get User Total Balances
To get user total balances, developer can call the WebSDK method: getBalances()
const getUserTotalBalance = async () => {
const userTotalBalance = await sphereoneSdk.getBalances();
console.log("userTotalBalance", JSON.stringify(userTotalBalance));
};
This method follows similarly to the getUserInfo
example above.
Create a Charge/Transaction
To create a charge
, or payment transaction
, in order to proceed with payments within SphereOne, developer would need to create a charge
object, which contains all the necessary information pertaining to the purchase such as the individual making the purchase, the item of the purchase, the total amount, etc.
To create a charge
, we need to use the WebSDK's method: createCharge
// importing the initialized WebSDK
import { sphereoneSdk } from "your-imported-file";
// an enum class of Chains that SphereOne supports
import { SupportedChains } from "websdk";
// ...
const [chargeId, setChargeId] = useState("");
const [paymentLink, setPaymentLink] = useState("");
const createCharge = async () => {
try {
const charge = await sphereoneSdk.createCharge({
chain: SupportedChains.SOLANA,
symbol: "SOL",
amount: 0.9, // total amount for entire charge
tokenAddress: "So11111111111111111111111111111111111111112",
successUrl: "https://your-website.com/success",
cancelUrl: "https://your-website.com/cancel",
items: [
{
name: "Your Item",
image: "https://your-image-url.somewhere.com",
amount: 0.9, // amount of the individual item
quantity: 1
}
]
});
setChargeId(charge.chargeId);
setPaymentLink(charge.paymentUrl);
} catch (e: any) {
console.error(e);
}
};
// ...
createCharge
has a set of parameters that must be set. More info can be found here at SphereOne API references - Create Charge.
In the above code example, a charge is created for a purchase involving SOLANA. To create a successful charge, we must pass a list of items that users want to purchase, the tokenAddress for SOLANA Chain
, followed by successUrl
and cancelUrl
.
NOTE: It's a bit inconvenient right now, but more updates will come to make this easier and more convenient.
If the charge
is successful, the response for charge in the above example, should be:
{
chargeId: "a-charge-id",
paymentUrl: "https://a-payment-link/a-charge-id"
}
What is absolutely needed is the chargeId
returned by createCharge
since that is the reference to the actual purchase that's going to be made, in the next step.
Once the chargeId
is retrieved or saved for later usage, you can continue with making payments in WebSDK.
As for the paymentUrl
returned by createCharge
, it is a dynamic link that can take user to SphereOne's Checkout Page
, similar to Stripe
, where similar functionality for paying for the charge
is implemented.
Pay for the Created Charge/Transaction
There are two ways to pay
for the charge
in the previous example.
- Use WebSDK method
payCharge
and pass in thechargeId
. - Open a popup or redirect user with the
paymentUrl
to SphereOne'sCheckout Page
, where functionality forpayCharge
is also implemented.
Note: To use the first option (payCharge method) we must first have the user enter their pin code. If we do not do this, the payment will not be triggered.
Note: To use the first option (payCharge method) we must first have the user enter their pin code. If we do not do this, the payment will not be triggered.
Below is an example of how to prompt the pin code popup.
First in the page where the button that triggers the popup for the user to enter his pin code is located, we must add this piece of code, to receive the pin code response and store it inside the SDK.
// importing the initialized WebSDK
import { sphereoneSdk } from "your-imported-file";
// ...
useEffect(() => {
sdk.pinCodeHandler()
}, [])
// ...
The method that opens the popup with the pin code display is called openPinCode()
we must pass as a parameter the chargeId
we want to pay, below is an example of the complete code to open the popup and get the response.
// importing the initialized WebSDK
import { sphereoneSdk } from "your-imported-file";
// ...
// these are from previous section from: https://docs.sphereone.xyz/docs/create-charge#web-sdk
const [chargeId, setChargeId] = useState("");
// ... refer to `Create a Charge/Transaction` Section example
// we need this piece of code to handle the callback for pin code popup
useEffect(() => {
sdk.pinCodeHandler()
}, [])
const pincode = () => {
try {
// passing in the `chargeId` set
sdk.openPinCode(chargeId)
} catch (e: any) {
console.error(e)
}
}
// ...
Once the user has entered the pin code, we are ready to call the payCharge
function to complete the payment of the previously created transaction.
Below is example of how to call payCharge
in WebSDK:
// importing the initialized WebSDK
import { sphereoneSdk } from "your-imported-file";
// ...
// these are from previous section from: https://docs.sphereone.xyz/docs/create-charge#web-sdk
const [chargeId, setChargeId] = useState("");
const [paymentLink, setPaymentLink] = useState("");
// ... refer to `Create a Charge/Transaction` Section example
const pay = async () => {
try {
// passing in the `chargeId` set
await sphereoneSdk.payCharge(chargeId);
} catch (e: any) {
console.error(e);
}
};
// ...
If payCharge
fails because consumer don't have or have enough funds in their Wallets, then payCharge
will return an error code
, which frontend-client can consume to determine what to do.
Below is an example response returned by payCharge
, if user doesn't have or have enough funds for completing the transaction.
{
"data": {
"status": "FAILURE",
"onrampLink": "https://sphereone-on-ramp-link/12345"
},
"error": {
"code": "sphereone-error-code",
"message": "sphereone error message"
}
}
To handle for this error, the simple payCharge
example can be modified to handle this error flow.
// importing the initialized WebSDK
import { sphereoneSdk } from "your-imported-file";
// ...
const pay = async () => {
try {
// trigger `pay` and listen for `result`
const result = await sphereoneSdk.payCharge(chargeId);
alert("Payment successful");
// you can also show the route created
console.log("route created =>", result.route)
} catch (e: any) {
// the error could be related to the user not having sufficients funds
// in that case the error contains a link to our PWA to easily onramp money
if(e.onrampLink){
alert(
"Not enough funds to pay with SphereOne. We will redirect you to the onramp page."
);
window.open(e.onrampLink, "Popup", 'width=800, height=850'); // open a pop-up
}
// the error is not solved with an onrampLink
else alert(`${e.message}`);
}
};
// ...
As shown in the code example above for payCharge
, if payCharge
fails because consumer doesn't have any or enough funds in Sphere Wallets to make the purchase, then payCharge
will return an error, which frontend-client can consume to determine what to do.
As shown in the code example above for payCharge
, frontend-client can check for the error.onrampLink
in the JSON response and utilize it in the JSON response to redirect or show a popup for consumer to proceed.
The onrampLink
will direct consumer to the SphereOne Wallet site. Here, consumer can utilize SphereOne's many on-ramp providers to add funds into theirWallets.
Once consumer has successfully added funds to their Wallets, then consumer can resume their payment.
It is a little inconvenient at the moment to handle this error flow manually. But more improvements will be made to handle that internally.
Transfer NFT
We must first have the user enter their pin code. If we do not do this, the transfer will not be triggered.
We must first have the user enter their pin code. If we do not do this, the transfer will not be triggered.
Note: At the moment we are only supporting Immutable X and Solana chains for NFT transfers.
Below is an example of how to prompt the pin code popup.
First in the page where the button that triggers the popup for the user to enter his pin code is located, we must add this piece of code, to receive the pin code response and store it inside the SDK.
// importing the initialized WebSDK
import { sphereoneSdk } from "your-imported-file";
// ...
useEffect(() => {
sdk.pinCodeHandler()
}, [])
// ...
The method that opens the popup with the pin code display is called openPinCode()
we have to pass as parameter the operation we want to perform, in this case: SEND_NFT
. Below is an example of the complete code to open the popup and get the response.
// importing the initialized WebSDK
import { sphereoneSdk } from "your-imported-file";
// we need this piece of code to handle the callback for pin code popup
useEffect(() => {
sdk.pinCodeHandler()
}, [])
const pincode = () => {
try {
// passing in the `chargeId` set
sdk.openPinCode("SEND_NFT")
} catch (e: any) {
console.error(e)
}
}
// ...
Once the user has entered the pin code, we are ready to call the transferNft
function to start with the transfer of the NFT.
Below is example of how to call transferNFT
in WebSDK:
// importing the initialized WebSDK
import { sphereoneSdk } from "your-imported-file";
const transferNft = async () => {
try {
await sphereoneSdk.transferNft({
chain: "nft_chain", // we recommend to use our enum `SupportedChains`. Ex: SupportedChains.ETHEREUM
fromAddress: "nft_owner_wallet",
toAddress: "destination_address",
nftTokenAddress: "nft_token_address",
tokenId?: "nft_token_id", // this parameter is only not required if the chain is SOLANA
reason?: "custom_message"
});
} catch (e: any) {
console.error(e);
}
};
// ...
With this we should have already made the transfer of NFT successfully, in case of any error with the blockchain during the transfer, the response of the function will include a message with the error.
Sign Out
To sign out of WebSDK, please invoke the WebSDK's logout functionality: logout()
import { sphereoneSdk } from "./your-implementation-file";
const logout = () => {
try {
sphereoneSdk.logout();
setIsLoggedIn(false); // set internal state on client side to false
} catch (e: any) {
console.error(e);
}
};
This should clear the current login session, and allow user to re-login again.
Pin code
Add new pin code
To add a new pin code to a user who does not currently have a pin code created, proceed as follows:
import { sphereoneSdk } from "./your-implementation-file";
const addPincode = () => {
try {
sphereoneSdk.addPinCode();
} catch (e: any) {
console.error(e);
}
};
Executing the addPincode()
method will open a popup window, in which the user will be asked to enter and confirm their new pin code. Upon successful addition of this new pin code, a confirmation window will appear confirming that this new code was added for the user.
Open pin code popup
At the moment there are two operations
for which you would need to open the popup for the user to enter his pin code, in both cases it is necessary for the user to enter the pin code configured in their account for security reasons.
- Pay a charge
- Send an NFT
Below is an example code to open the pin code window for the first case of paying a charge. It is necessary to pass as a parameter the chargeId
// importing the initialized WebSDK
import { sphereoneSdk } from "your-imported-file";
// ...
// these are from previous section from: https://docs.sphereone.xyz/docs/create-charge#web-sdk
const [chargeId, setChargeId] = useState("");
// ... refer to `Create a Charge/Transaction` Section example
// we need this piece of code to handle the callback for pin code popup
useEffect(() => {
sdk.pinCodeHandler()
}, [])
const pincode = () => {
try {
// passing in the `chargeId` set
sdk.openPinCode(chargeId)
} catch (e: any) {
console.error(e)
}
}
// ...
In case you want to send an NFT to another wallet, it is very similar only that we have to pass the SEND_NFT
operation as a parameter. Below is an example code to perform this operation.
// importing the initialized WebSDK
import { sphereoneSdk } from "your-imported-file";
// ...
// we need this piece of code to handle the callback for pin code popup
useEffect(() => {
sdk.pinCodeHandler()
}, [])
const pincode = () => {
try {
// passing in the `SEND_NFT` operation
sdk.openPinCode("SEND_NFT")
} catch (e: any) {
console.error(e)
}
}
// ...
Notes:
- It is necessary to have the
pinCodeHandler
method in order to handle the pin code response. - If the user does not enter his pin code, the
payCharge
ortransferNft
method will fail.
Updated 6 months ago