This guide describes the process of integrating with Gateway’s Storage Layer directly, from initial setup to storage confirmation.
Check out the
Developer API instead for commonly-used operations.
Integration Flow
1. Identity Creation
Encryption Keys
Generate a PRE-compatible key pair for encryption operations. For detailed instructions on key generation, see PRE Key Documentation.
Signing Keys
Generate secp256k1 signing keys for transaction authentication
import { Wallet } from 'ethers';
// Generate a new random wallet
const wallet = Wallet.createRandom();
// Get the private key (keep this secret!)
const privateKey = wallet.privateKey;
// Get the public key
const publicKey = wallet.publicKey;
// Get the Ethereum address
const address = wallet.address;
console.log('Private Key:', privateKey);
console.log('Public Key:', publicKey);
console.log('Address:', address);
2. File Assignment
Request a File ID from the Gateway Master Node using gRPC.
You must obtain an mTLS certificate from the Gateway team to network with our Storage Layer.See Authentication Requirements to generate your certificate.
const path = require('path');
const fs = require('fs');
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
// Load certificates
const rootCert = fs.readFileSync(path.join(__dirname, 'certs/ca.crt'));
const clientKey = fs.readFileSync(path.join(__dirname, 'certs/node.key'));
const clientCert = fs.readFileSync(path.join(__dirname, 'certs/node.crt'));
// Create SSL credentials with mTLS
const sslCreds = grpc.credentials.createSsl(
rootCert,
clientKey,
clientCert
);
// Load proto file
const packageDefinition = protoLoader.loadSync(
path.join(__dirname, 'master.proto'),
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
}
);
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
const master = protoDescriptor.master;
// Create client instance
const stage: 'testnet' | 'mainnet' = "testnet";
const client = new master.GatewayFS(
`master.${stage}.gateway.tech:19333`,
sslCreds
);
// Make Assign RPC call
client.assign(
{
count: 1,
replication: '000',
collection: 'default'
},
(error, response) => {
if (error) {
console.error('Error:', error);
return;
}
console.log('Assign Response:', response);
}
);
3. Chain Registration
Initialize the file record on the payment chain to establish ownership and permissions:
Contract information coming soon.
4. File Upload
Upload your file to the Gateway network using the assigned File ID:
import { ethers } from 'ethers';
import { readFileSync } from 'fs';
const stage: "testnet" | "mainnet" = "testnet";
const fileId: string = ""; // todo: update with allocated fileId
const privateKey: string = ""; // todo: signer's private key
// Sign the fileId directly
const wallet = new ethers.Wallet(privateKey);
const signature = await wallet.signMessage(fileId);
// Load file data
const fileData = readFileSync('path/to/your/file.txt');
const formdata = new FormData();
formdata.append("data", new Blob([fileData]));
formdata.append("signature", signature);
const requestOptions = {
method: "POST",
body: formdata,
redirect: "follow"
};
fetch(`https://master.${stage}.gateway.tech:9333/${fileId}`, requestOptions)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.error(error));
Best Practices
- Implement retry logic for API calls
- Verify transaction confirmations
- Validate file integrity
- Monitor storage quotas
- Handle API rate limits
Security Considerations
- Secure API key management
- Client-side encryption before upload
- Checksum verification
- Transaction signature verification
- Regular permission audits
Error Handling
Common integration points requiring error handling:
-
API Errors
- Network connectivity issues
- Authentication failures
- Rate limiting
- Invalid requests
-
Chain Transaction Errors
- Transaction failures
- Invalid parameters
- Insufficient funds
- Permission errors