API
Shadow Drive exposes an API that you can interact directly without the need of the CLI or SDK. You may build on top of these methods.
post
https://shadow-storage.genesysgo.net
storage-account
post
https://shadow-storage.genesysgo.net
storage-account-info
post
https://shadow-storage.genesysgo.net
upload
post
https://shadow-storage.genesysgo.net
edit
post
https://shadow-storage.genesysgo.net
list-objects
post
https://shadow-storage.genesysgo.net
list-objects-and-sizes
post
https://shadow-storage.genesysgo.net
get-object-data
post
https://shadow-storage.genesysgo.net
delete-file
post
https://shadow-storage.genesysgo.net
add-storage
post
https://shadow-storage.genesysgo.net
reduce-storage (updated)
post
https://shadow-storage.genesysgo.net
make-immutable (updated)
import bs58 from 'bs58'
import nacl from 'tweetnacl'
import crypto from 'crypto'
// `files` is an array of each file passed in.
const allFileNames = files.map(file => file.fileName)
const hashSum = crypto.createHash("sha256")
// `allFileNames.toString()` creates a comma-separated list of all the file names.
const hashedFileNames = hashSum.update(allFileNames.toString())
const fileNamesHashed = hashSum.digest("hex")
// `storageAccount` is the string representation of a storage account pubkey
let msg = `Shadow Drive Signed Message:\nStorage Account: ${storageAccount}\nUpload files with hash: ${fileNamesHashed}`;
const fd = new FormData();
// `files` is an array of each file passed in
for (let j = 0; j < files.length; j++) {
fd.append("file", files[j].data, {
contentType: files[j].contentType as string,
filename: files[j].fileName,
});
}
// Expect the final message string to look something like this if you were to output it
// Shadow Drive Signed Message:
// Storage Acount: ABC123
// Upload files with hash: hash1
// If the message is not formatted like above exactly, it will fail message signature verification
// on the Shadow Drive Network side.
const encodedMessage = new TextEncoder().encode(message);
// Uses https://github.com/dchest/tweetnacl-js to sign the message. If it's not signed in the same manor,
// the message will fail signature verification on the Shadow Network side.
// This will return a base58 byte array of the signature.
const signedMessage = nacl.sign.detached(encodedMessage, keypair.secretKey);
// Convert the byte array to a bs58-encoded string
const signature = bs58.encode(signedMessage)
fd.append("message", signature);
fd.append("signer", keypair.publicKey.toString());
fd.append("storage_account", storageAccount.toString());
fd.append("fileNames", allFileNames.toString());
const request = await fetch(`${SHDW_DRIVE_ENDPOINT}/upload`, {
method: "POST",
body: fd,
});
import bs58 from 'bs58'
import nacl from 'tweetnacl'
// `storageAccount` is the string representation of a storage account pubkey
// `fileName` is the name of the file to be edited
// `sha256Hash` is the sha256 hash of the new file's contents
const message = `Shadow Drive Signed Message:\n StorageAccount: ${storageAccount}\nFile to edit: ${fileName}\nNew file hash: ${sha256Hash}`
// Expect the final message string to look something like this if you were to output it
// Shadow Drive Signed Message:
// Storage Acount: ABC123
// File to delete: https://shadow-drive.genesysgo.net/ABC123/file.png
// If the message is not formatted like above exactly, it will fail message signature verification
// on the Shadow Drive Network side.
const encodedMessage = new TextEncoder().encode(message);
// Uses https://github.com/dchest/tweetnacl-js to sign the message. If it's not signed in the same manor,
// the message will fail signature verification on the Shadow Network side.
// This will return a base58 byte array of the signature.
const signedMessage = nacl.sign.detached(encodedMessage, keypair.secretKey);
// Convert the byte array to a bs58-encoded string
const signature = bs58.encode(signedMessage)
const fd = new FormData();
fd.append("file", fileData, {
contentType: fileContentType as string,
filename: fileName,
});
fd.append("signer", keypair.publicKey.toString())
fd.append("message", signature)
fd.append("storage_account", storageAccount)
const uploadResponse = await fetch(`${SHDW_DRIVE_ENDPOINT}/edit`, {
method: "POST",
body: fd,
});
import bs58 from 'bs58'
import nacl from 'tweetnacl'
// `storageAccount` is the string representation of a storage account pubkey
// `url` is the link to the shadow drive file, just like the previous implementation needed the url input
const message = `Shadow Drive Signed Message:\nStorageAccount: ${storageAccount}\nFile to delete: ${url}`
// Expect the final message string to look something like this if you were to output it
// Shadow Drive Signed Message:
// Storage Acount: ABC123
// File to delete: https://shadow-drive.genesysgo.net/ABC123/file.png
// If the message is not formatted like above exactly, it will fail message signature verification
// on the Shadow Drive Network side.
const encodedMessage = new TextEncoder().encode(message);
// Uses https://github.com/dchest/tweetnacl-js to sign the message. If it's not signed in the same manor,
// the message will fail signature verification on the Shadow Network side.
// This will return a base58 byte array of the signature.
const signedMessage = nacl.sign.detached(encodedMessage, keypair.secretKey);
// Convert the byte array to a bs58-encoded string
const signature = bs58.encode(signedMessage)
const deleteRequestBody = {
signer: keypair.publicKey.toString(),
message: signature,
location: options.url
}
const deleteRequest = await fetch(`${SHDW_DRIVE_ENDPOINT}/delete-file`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(deleteRequestBody)
})
Last modified 17d ago