XP Network JS API
Work In Progress / Alpha Stage Library
Bridging steps:
- [x] 1. Installing the library
- [x] 2. Importing the dependencies
- [x] 3. Getting the signer objects
- [x] 4. Getting the Chain inner objects
- [x] 5. Listing NFTs
- [x] 6. Approving
- [x] 7. Transferring NFTs between chains
- [x] Minting NFTs(optional)
- [x] Estimating the TX fee on the target chain (optional)
- [ ] ... and there's much more to come
To list and transfer NFTs, follow the steps below:
Make sure nodejs is installed on your machine.
1. Install the libraries required for the project:
yarn add xp.network @elrondnetwork/erdjs ethers @taquito/taquito @temple-wallet/dapp
OR
npm i --save xp.network @elrondnetwork/erdjs ethers @taquito/taquito @temple-wallet/dapp
To import the latest version of xp.network v.2.0 library:
yarn add "git+https://github.com/xp-network/xpjs#bleeding-edge" @elrondnetwork/erdjs ethers @taquito/taquito @temple-wallet/dapp
import {
ChainFactoryConfigs,
ChainFactory,
Chain,
AppConfigs,
ChainParams,
} from "xp.network";
(async () => {
// Instantiate the chain factory for the
// Connecting to the mainnnets of all the blockchains:
const mainnetConfig = await ChainFactoryConfigs.MainNet();
const mainnetFactory: ChainFactory = ChainFactory(
AppConfigs.MainNet(),
mainnetConfig
);
// Connecting to the testnets of all the blockchains:
const testnetConfig = await ChainFactoryConfigs.TestNet();
const testnetFactory: ChainFactory = ChainFactory(
AppConfigs.TestNet(),
testnetConfig
);
// Switching between the mainnets & the testnets:
const factory: ChainFactory = mainnetFactory;
const CONFIG: Partial<ChainParams> = mainnetConfig;
})();
3. Get the signer objects
3.1 Example of getting the signer object (for manual EVM testing in the BE)
Avoid using 3.1 setup in production. Use it for initial or backend testing only.
Add your private key to the environment:
touch .env
echo "SK=<Replace this with your Private Key>" >> .env
// EVM chains compatible wallet:
import { Wallet } from "ethers";
import { config } from 'dotenv';
config();
// EVM signer for testing in the BE
const signer = new Wallet(
process.env.SK!,
// Replace 'polygonParams'
// with the relevant parameter
// from the table below
CONFIG.polygonParams?.provider
);
Chain | Parameters | Chain Nonce |
---|---|---|
Elrond | elrondParams | 2 |
BSC | bscParams | 4 |
Ethereum | ropstenParams | 5 |
Avalanche | avalancheParams | 6 |
Polygon | polygonParams | 7 |
Fantom | fantomParams | 8 |
Tron | tronParams | 9 |
Harmony | harmonyParams | 12 |
xDai | xDaiParams | 14 |
Algorand | algorandParams | 15 |
Fuse | fuseParams | 16 |
Tezos | tezosParams | 18 |
Velas | velasParams | 19 |
Aurora | auroraParams | 21 |
Godwoken | godwokenParams | 22 |
Gatechain | gatechainParams | 23 |
VeChain | vechainParams | 25 |
// EVM chains compatible signer:
import ethers from "ethers";
const signer = new ethers.providers.Web3Provider(window.ethereum).getSigner();
// ELROND provider:
import { ExtensionProvider } from "@elrondnetwork/erdjs/out";
const elrondSigner = ExtensionProvider.getInstance();
// Address is fetched from tronweb
(async () => {
const addresses = await window.tronLink.tronWeb.request({
method: "tron_requestAccounts",
});
const tronSigner = addresses[0];
})();
import { typedAlgoSigner } from "xp.network/dist/helpers/algorand";
// Use the typedAlgoSigner function to get access to the Algorand signer
const algorandSigner = typedAlgoSigner();
import { TempleWallet } from "@temple-wallet/dapp";
(async () => {
try {
const available = await TempleWallet.isAvailable();
if (!available) {
throw new Error("Temple Wallet is not installed");
}
const tezosSigner = new TempleWallet("bridge.xp.network");
} catch (error) {
console.error("Error:", error);
}
})();
For the ways of connecting the wallets in the FE check-out our bridge repository
(async () => {
// Inner Object ================================ Chain Nonce
const bsc = await factory.inner(Chain.BSC); // 4
const ethereum = await factory.inner(Chain.ETHEREUM); // 5
const avax = await factory.inner(Chain.AVALANCHE); // 6
const polygon = await factory.inner(Chain.POLYGON); // 7
const fantom = await factory.inner(Chain.FANTOM); // 8
const harmony = await factory.inner(Chain.HARMONY); // 12
const gnosis = await factory.inner(Chain.XDAI); // 14
const fuse = await factory.inner(Chain.FUSE); // 16
const velas = await factory.inner(Chain.VELAS); // 19
const aurora = await factory.inner(Chain.AURORA); // 21
const godwoken = await factory.inner(Chain.GODWOKEN); // 22
const gatechain = await factory.inner(Chain.GATECHAIN); // 23
const vechain = await factory.inner(Chain.VECHAIN); // 25
// Non-EVM chains:
// Inner Object ================================ Chain Nonce
const elrond = await factory.inner(Chain.ELROND); // 2
const tron = await factory.inner(Chain.TRON); // 9
const algorand = await factory.inner(Chain.ALGORAND); // 15
const tezos = await factory.inner(Chain.TEZOS); // 18
})();
This operation does not depend on a wallet since reading operations are free and, therefore, do not require signing.
(async () => {
// EVM:
const web3Nfts = await factory.nftList(
harmony, // The chain of interest
"0x...." // The public key of the NFT owner in a web3 chain
);
// Elrond:
const elrondNfts = await factory.nftList(
elrond, // The chain of interest
"erd1...." // The public key of the NFT owner in Elrond
);
// Tron:
const tronNfts = await factory.nftList(
tron, // The chain of interest
"TJuG..." // The public key of the NFT owner in Tron
);
// Algorand:
const algoNfts = factory.nftList(
algorand, // Algorand chain internal object
"PUPTH..." // The public key of the NFT owner in Algorand
);
// Tezos:
const tezosNfts = await factory.nftList(
tezos, // Tezos chain internal object
"tz1..." // The public key of the NFT owner in Tezos
);
})();
// Choosing an NFT to transfer:
const web3ChosenOne = web3Nfts[0];
const elrondChosenOne = elrondNfts[0];
const tronChosenOne = tronNfts[0];
const algoChosenOne = algoNfts[0];
const tezosChosenOne = tezosNfts[0];
// Checking the selected NFT object
console.log("EVM Selected NFT: ", web3ChosenOne);
console.log("Elrond Selected NFT: ", elrondChosenOne);
console.log("Tron Selected NFT: ", tronChosenOne);
console.log("Algorand Selected NFT: ", algoChosenOne);
console.log("Tezos Selected NFT: ", tezosChosenOne);
5.2 Example of console logged native BSC NFT object:
{
"boosterId": 10000000788939,
"id": "10002366816",
"txHash": "0x37c9b7c54ac05d5e00dd5cff06722fb67bed91ec91732875071f74bce8752e41",
"randomNumber": "0x1459a03e3d7a5510023e7385d438508d725dd19de2237c6c1d79a9883b6dc0b3",
"image": "https://assets.polkamon.com/images/Unimons_T02C03H06B04G00.jpg",
"external_url": "https://polkamon.com/polkamon/T02C03H06B04G00",
"description": "The Unifairy are the most magical and fairest of Polkamon. Their wings stretch into the realms beyond this world, enchanting those around her by her unique disposition.",
"name": "Unifairy",
"initialProbabilities": {
"horn": 0.2,
"color": 0.25,
"background": 1,
"glitter": 0.99,
"type": 0.135
},
"attributes": [
{
"trait_type": "Type",
"value": "Unifairy"
},
{
"trait_type": "Horn",
"value": "Spiral Horn"
},
{
"trait_type": "Color",
"value": "Blue"
},
{
"trait_type": "Background",
"value": "Mountain Range"
},
{
"trait_type": "Opening Network",
"value": "Binance Smart Chain"
},
{
"trait_type": "Glitter",
"value": "No"
},
{
"trait_type": "Special",
"value": "No"
},
{
"display_type": "date",
"trait_type": "Birthday",
"value": 1633650473
},
{
"display_type": "number",
"trait_type": "Booster",
"value": 10000000788939
}
],
"opening_network": "Binance Smart Chain",
"background_color": "FFFFFF",
"animation_url": "https://assets.polkamon.com/videos/Unimons_T02C03H06B04G00.mp4",
"code": "T02C03H06B04G00",
"uri": "https://meta.polkamon.com/meta?id=10002366816",
"native": {
"chainId": "4",
"tokenId": "10002366816",
"owner": "0x0d7df42014064a163DfDA404253fa9f6883b9187",
"contract": "0x85f0e02cb992aa1f9f47112f815f519ef1a59e2d",
"symbol": "PMONC",
"name": "PolkamonOfficialCollection",
"uri": "https://meta.polkamon.com/meta?id=10002366816",
"contractType": "ERC721"
}
}
5.3 Example of the console logged wrapped NFT from BSC on Velas
{
"name": "DRVR NOT LVR",
"description": "Cliff Blank | Community Pool Drop\n\nWe would need a license to love, there would be fewer lines, fewer misunderstandings but definitely more accidents. \nThe arteries of our heart would be 4 lanes so that we could reach love in a short time. Of course, there could always be works and exits closed but at least we would have fewer surprises and we would react accordingly, choosing another exit or deciding to continue on our way.",
"decimals": 0,
"isBooleanAmount": true,
"image": "https://ipfs.infura.io/ipfs/QmX4n4QJBsGmVuszy1fXMJHpGnpkp9BePVJNQ8Lf18yA8z",
"artifactUri": "https://ipfs.infura.io/ipfs/QmX4n4QJBsGmVuszy1fXMJHpGnpkp9BePVJNQ8Lf18yA8z",
"wrapped": {
"contract": "0x1BFb3FbCf1ce331B7AAE03a3c0Bf3AcF685F4bD6",
"tokenId": "10",
"contractType": 721,
"origin": "14",
"original_uri": "https://ipfs.infura.io/ipfs/QmdtemgadGPgWSn9Lq1RvQn4Q2ofEpRNr7ox8oMyNWJ9ma",
"mint_with": "0x3a1d5a87c5f0c2f5c5e079b0f234d8797ee0e9b4",
"source_mint_ident": "0x1BFb3FbCf1ce331B7AAE03a3c0Bf3AcF685F4bD6"
},
"attributes": [
{
"trait_type": "Original Chain",
"value": "xDai"
},
{
"trait_type": "Original Chain Nonce",
"value": "14"
},
{
"trait_type": "Original URI",
"value": "https://ipfs.infura.io/ipfs/QmdtemgadGPgWSn9Lq1RvQn4Q2ofEpRNr7ox8oMyNWJ9ma"
}
],
"displayUri": "https://ipfs.infura.io/ipfs/QmX4n4QJBsGmVuszy1fXMJHpGnpkp9BePVJNQ8Lf18yA8z",
"thumbnailUri": "https://ipfs.infura.io/ipfs/QmX4n4QJBsGmVuszy1fXMJHpGnpkp9BePVJNQ8Lf18yA8z",
"ipfs": false
}
(async () => {
// EVM example
const isApprovedEVM = await harmony.approveForMinter(web3ChosenOne, signer);
console.log("Is Approved in an EVM:", isApprovedEVM);
// Elrond example
const isApprovedElrond = await elrond.approveForMinter(
elrondChosenOne,
elrondSigner
);
console.log("Is Approved in Elrond:", isApprovedElrond);
// Tron example
const isApprovedTron = await elrond.approveForMinter(
tronChosenOne,
tronSigner
);
console.log("Is Approved in Tron:", isApprovedTron);
// Algorand example
const isApprovedAlgorand = await algorand.approveForMinter(
algoChosenOne,
algorandSigner
);
console.log("Is Approved in Algorand:", isApprovedAlgorand);
// Tezos example
const isApprovedTezos = await algorand.approveForMinter(
tezosChosenOne,
tezosSigner
);
console.log("Is Approved in Tezos:", isApprovedTezos);
})();
(async () => {
// EVM compatible chains example:
const web3Result = await factory.transferNft(
harmony, // The Source Chain.
bsc, // The Destination Chain.
theChosenOne, // The NFT object you have chosen from the list.
signer, // The web3 signer object (see p. 3.2 above).
"ADDRESS OF THE RECEIVER" // The address whom you are transferring the NFT to.
);
console.log(web3Result);
// Elrond example:
const elrondResult = await factory.transferNft(
elrond, // The Source Chain.
tron, // The Destination Chain.
elrondChosenOne, // The NFT object you have chosen from the list.
elrondSigner, // The Elrond signer object (see p. 3.3 above).
"ADDRESS OF THE RECEIVER" // The address whom you are transferring the NFT to.
);
console.log(elrondResult);
// Tron example:
const tronResult = await factory.transferNft(
tron, // The Source Chain.
elrond, // The Destination Chain.
tronChosenOne, // The NFT object you have chosen from the list.
tronSigner, // The Tron signer object (see p. 3.4 above).
"ADDRESS OF THE RECEIVER" // The address whom you are transferring the NFT to.
);
console.log(tronResult);
// Algorand example:
const algorandResult = await factory.transferNft(
algorand, // The Source Chain.
elrond, // The Destination Chain.
algoChosenOne, // The NFT object you have chosen from the list.
algorandSigner, // The Tron signer object (see p. 3.5 above).
"ADDRESS OF THE RECEIVER" // The address whom you are transferring the NFT to.
);
console.log(algorandResult);
// Tezos example:
const tezosResult = await factory.transferNft(
tezos, // The Source Chain.
velas, // The Destination Chain.
algoChosenOne, // Or the NFT object you have chosen from the list.
algorandSigner, // The Tron signer object (see p. 3.5 above).
"ADDRESS OF THE RECEIVER" // The address whom you are transferring the NFT to.
);
console.log(tezosResult);
})();
Minting NFTs on EVM chains, Elrond & Tron
- Just call the mint function on the factory with suitable arguments.
- For Web3 Chains:
(async () => {
// Web3Provider generally refers to a walletProvider like Metamask.
const receipt = await factory.mint(
avax, // The chain where to mint
signer, // The browser injected signer
{
// Could be an IPFS URL or Any URL that points to a Metadata
uris: [metadata.url],
// Description of your NFT. Can be an object.
attrs: description,
// A name that defines your NFT.
name: name,
// The contract with which you want to mint the NFT.
contract: "Can be fetched from the mainnetConfig or testnetConfig",
}
);
})();
- For Elrond:
(async () => {
const receipt = await factory.mint(
elrond, // The chain where to mint
elrondSigner, // The browser injected signer
{
// Could be an IPFS URL or Any URL that points to a Metadata
uris: [metadata.url],
// Description of your NFT. Can be an object.
attrs: description,
// A name that defines your NFT.
name: name,
// The identifier with which you want to mint the NFT. You have to own this identifier. i.e.
identifier: "XPNFT-eda5d0-c5",
}
);
})();
- For Tron:
const receipt = await factory.mint(avax, tronSigner, {
// Could be an IPFS URL or Any URL that points to a Metadata
uris: [metadata.url],
// Description of your NFT. Can be an object.
attrs: description,
// A name that defines your NFT.
name: name,
// The contract with which you want to mint the NFT.
contract: "Can be fetched from the mainnetConfig or testnetConfig",
});
P.S. The library is a work in progress. More features will be added soon.
Estimating the transaction fee on the target chain
(async () => {
const feeEstimation = await factory.estimateFees(
algorand, // The Source Chain.
tezos, // The Destination Chain.
algoChosenOne, // The NFT object you have chosen from the list.
"tz1..." // The public key of the NFT owner in Tezos
);
console.log(`The estimated fee on Tezos is: ${feeEstimation} Algos`);
})();
- In case you're using the library in a console application and getting errors, go to:
- node_modules/xpnet-nft-list/dist/nft-list/model/moralis/MoralisNftListService.js
Now your line #7 looks like this (to be used in the FE):
7 const moralis_1 = __importDefault(require("moralis"));
Change it like so (for BE usage):
7 const moralis_1 = __importDefault(require("moralis/node"));