
Storage capacity
DISTRIBUTED NODES
STORAGE ORDERS
REPLICAS ON AVERAGE
With decentralization at its core Crust Network is a purpose built layer 1 blockchain providing composable cloud storage solutions for developers, builders and end-users of all ecosystems.
A global network of nodes ensures true decentralization at its foundation, along with vast storage resources.
Powering IPFS with an incentive and service layer, to assure data availability and redundancy through a trustless protocol.
Omnichain storage services for frictionless interoperability across multiple ecosystems and in the most native way.
Access a decentralized and permissionless storage market catering to permanent and flexible storage needs.




















Api Code
const got = require('got');
const { create, globSource } = require('ipfs-http-client');
const { Keyring } = require('@polkadot/keyring');
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
// 1. Get all inputss
const path = './build';
const seeds = process.argv[2];
const ipfsGateway = 'https://crustwebsites.net'; // IPFS Web3 Authed Gateway address
const ipfsPinningService = 'https://pin.crustcode.com/psa'; // IPFS Web3 Authed Pinning Service address
// 2. Construct auth header
const keyring = new Keyring();
const pair = keyring.addFromUri(seeds);
const sig = pair.sign(pair.address);
const sigHex = '0x' + Buffer.from(sig).toString('hex');
const authHeader = Buffer.from(`sub-${pair.address}:${sigHex}`).toString('base64');
// 3. Create ipfs http client
const ipfs = create({
url: ipfsGateway + '/api/v0',
headers: {
authorization: 'Basic ' + authHeader
}
});
const { cid } = await ipfs.add(globSource(path, '**/*'));
if (cid) {
console.log(cid.toV0().toString());
} else {
throw new Error('IPFS add failed, please try again.');
}
// 4. Pin to crust with IPFS standard W3Authed pinning service
const {body} = await got.post(
ipfsPinningService + '/pins',
{
headers: {
authorization: 'Bearer ' + authHeader
},
json: {
cid: cid.toV0().toString(),
name: 'crust-demo'
}
}
);
if (body) {
const rid = JSON.parse(body)['requestId'];
console.log(body, rid);
// 5. Query pinning status through pinning service
while (true) {
const {body: pinningStat} = await got(
ipfsPinningService + `/pins/${rid}`,
{
headers: {
authorization: 'Bearer ' + authHeader
}
}
);
console.log(pinningStat); // After success, you can query the cid on Crust
await timeout(1000);
}
} else {
console.log(body);
throw new Error('Crust pin failed, please try again.');
}
}
main().catch(error => {
console.error(error.message);
});
Api Code
Api Code
const { ethers } = require("ethers");
// Base
const ABI = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"customer","type":"address"},{"indexed":false,"internalType":"address","name":"merchant","type":"address"},{"indexed":false,"internalType":"string","name":"cid","type":"string"},{"indexed":false,"internalType":"uint256","name":"size","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isPermanent","type":"bool"}],"name":"Order","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"address","name":"nodeAddress","type":"address"}],"name":"addOrderNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getNodesNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"bool","name":"isPermanent","type":"bool"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nodeArray","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nodes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"cid","type":"string"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"bool","name":"isPermanent","type":"bool"}],"name":"placeOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"cid","type":"string"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"address","name":"nodeAddress","type":"address"},{"internalType":"bool","name":"isPermanent","type":"bool"}],"name":"placeOrderWithNode","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"priceOracle","outputs":[{"internalType":"contract IPriceOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nodeAddress","type":"address"}],"name":"removeOrderNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"priceOracleAddress","type":"address"}],"name":"setPriceOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]`
const CONTRACT_ADDRESS = "0xE391613d2056e47F74ED5eF1d443d4CDB21AAAd9";
const CHAIN_URL = "https://ethereum-mainnet-rpc.allthatnode.com";
const PRIVATE_KEY = "0xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// File infomation
const fileCid = "QmTWBmGaUhEEusN5cftWFWjcegbfd9KftRND9EdsZrUvh2";
const fileSize = 44358;
const isPermanentStorage = false; // false means 6 months storage
async function main() {
// provider
const provider = new ethers.providers.JsonRpcProvider(CHAIN_URL)
// signer
const signer = new ethers.Wallet(PRIVATE_KEY, provider);
// contract instance
const storeContract = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer);
console.log("Get the file storage fee");
const price = await storeContract.getPrice(fileSize, isPermanentStorage);
console.log("Fee: " + price + " wei");
console.log("Place storge order");
const tx = await storeContract.placeOrder(fileCid, fileSize, isPermanentStorage, { value: price });
await tx.wait();
console.log("Done this");
}
(async () => {
await main();
})().catch(e => {
console.error(e);
});
Api Code
import fs from 'fs';
import path from 'path';
import { create, IPFSHTTPClient } from 'ipfs-http-client';
import { ethers } from 'ethers';
import { ApiPromise, WsProvider } from '@polkadot/api';
import { typesBundleForPolkadot } from '@crustio/type-definitions';
import { Keyring } from '@polkadot/keyring';
const crustChainEndpoint = 'wss://rpc.crust.network'; // More endpoints: https://github.com/crustio/crust-apps/blob/master/packages/apps-config/src/endpoints/production.ts#L9
const ipfsW3GW = 'https://crustipfs.xyz'; // More web3 authed gateways: https://github.com/crustio/ipfsscan/blob/main/lib/constans.ts#L29
const crustSeeds = 'xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx'; // Create account(seeds): https://wiki.crust.network/docs/en/crustAccount
const api = new ApiPromise({
provider: new WsProvider(crustChainEndpoint),
typesBundle: typesBundleForPolkadot,
});
main();
async function main() {
// I. Upload file to IPFS
// 1. Read file
const filePath = 'sampleFile.txt';
const fileContent = await fs.readFileSync(path.resolve(__dirname, filePath));
// 2. [Local] Create IPFS instance
const ipfsLocal = await create({ url: 'http://localhost:5001' });
// 2. [Gateway] Create IPFS instance
// Now support: ethereum-series, polkadot-series, solana, elrond, flow, near, ...
// Let's take ethereum as example
const pair = ethers.Wallet.createRandom();
const sig = await pair.signMessage(pair.address);
const authHeaderRaw = `eth-${pair.address}:${sig}`;
const authHeader = Buffer.from(authHeaderRaw).toString('base64');
const ipfsRemote = create({
url: `${ipfsW3GW}/api/v0`,
headers: {
authorization: `Basic ${authHeader}`
}
});
// 3. Add IPFS
const rst = await addFile(ipfsRemote, fileContent); // Or use IPFS local
console.log(rst);
// II. Place storage order
await placeStorageOrder(rst.cid, rst.size);
// III. [OPTIONAL] Add prepaid
// Learn what's prepard for: https://wiki.crust.network/docs/en/DSM#3-file-order-assurance-settlement-and-discount
const addedAmount = 100; // in pCRU, 1 pCRU = 10^-12 CRU
await addPrepaid(rst.cid, addedAmount);
// IV. Query storage status
// Query forever here ...
while (true) {
const orderStatus: any = (await getOrderState(rst.cid)).toJSON();
console.log('Replica count: ', orderStatus['reported_replica_count']); // Print the replica count
await new Promise(f => setTimeout(f, 1500)); // Just wait 1.5s for next chain-query
}
}
async function addFile(ipfs: IPFSHTTPClient, fileContent: any) {
// 1. Add file to ipfs
const cid = await ipfs.add(fileContent);
// 2. Get file status from ipfs
const fileStat = await ipfs.files.stat("/ipfs/" + cid.path);
return {
cid: cid.path,
size: fileStat.cumulativeSize
};
}
async function placeStorageOrder(fileCid: string, fileSize: number) {
// 1. Construct place-storage-order tx
const tips = 0;
const memo = '';
const tx = api.tx.market.placeStorageOrder(fileCid, fileSize, tips, memo);
// 2. Load seeds(account)
const kr = new Keyring({ type: 'sr25519' });
const krp = kr.addFromUri(crustSeeds);
// 3. Send transaction
await api.isReadyOrError;
return new Promise((resolve, reject) => {
tx.signAndSend(krp, ({events = [], status}) => {
console.log(`💸 Tx status: ${status.type}, nonce: ${tx.nonce}`);
if (status.isInBlock) {
events.forEach(({event: {method, section}}) => {
if (method === 'ExtrinsicSuccess') {
console.log(`✅ Place storage order success!`);
resolve(true);
}
});
} else {
// Pass it
}
}).catch(e => {
reject(e);
})
});
}
async function addPrepaid(fileCid: string, amount: number) {
// 1. Construct add-prepaid tx
const tx = api.tx.market.addPrepaid(fileCid, amount);
// 2. Load seeds(account)
const kr = new Keyring({ type: 'sr25519' });
const krp = kr.addFromUri(crustSeeds);
// 3. Send transaction
await api.isReadyOrError;
return new Promise((resolve, reject) => {
tx.signAndSend(krp, ({events = [], status}) => {
console.log(`💸 Tx status: ${status.type}, nonce: ${tx.nonce}`);
if (status.isInBlock) {
events.forEach(({event: {method, section}}) => {
if (method === 'ExtrinsicSuccess') {
console.log(`✅ Add prepaid success!`);
resolve(true);
}
});
} else {
// Pass it
}
}).catch(e => {
reject(e);
})
});
}
async function getOrderState(cid: string) {
await api.isReadyOrError;
return await api.query.market.filesV2(cid);
}
Elevating your IPFS experience, Crust Network serves as incentivized service layer, safeguarding your data with accessibility, replication, and long-term guarantees.

Upload and retrieve data with Crust’s dedicated IPFS gateways. Our gateways ensure highest performance for the best user experience on IPFS.
Pin your data to Crust and enjoy multiple replicas per file secured via a fully decentralized protocol and infrastructure. On-demand as well as permanently.
Inspect your storage orders directly on-chain or via our IPFS storage explorer to validate data availability, number of replicas and more.




