Publish UHRP Content with NanoStore
This package allows you to create Universal Hash Resolution Protocol (UHRP) content publications and hosting contracts for files and data. Since UHRP URLs are content-addressed, they are self-authenticating. Since any UHRP host can advertise the availability of content, discovery is no longer controlled by a trusted third party as is the case with HTTP.
Once you've uploaded, the content is available with NanoSeek, which automatically checks the integrity of the data.
Check out NanoStore UI to see a file upload example with React.
All the example code relies on the Babbage SDK to pay for a file to be hosted:
import { invoice, pay, upload } from 'nanostore-publisher'
// First, get "file" from an HTML file upload input.
// If you use React, get "file" from your form in the normal React-y way :)
const file = document.getElementById('upload').files[0]
// Decide how long the file is to be hosted on NanoStore.
// This is a number of minutes.
const hostingMinutes = 60 * 24 * 30 // For example, 30 days
// If not provided, the default nanostore URL is 'https://nanostore.babbage.systems'
const serverURL = 'https://nanostore.babbage.systems'
// Get an invoice for a file with this size and hosting duration
const invoice = await invoice({
fileSize: file.size,
retentionPeriod: hostingMinutes,
config: {
nanostoreURL: serverURL
}
})
// Automatically pay the invoice with the Babbage SDK
const pay = await pay({
config: {
nanostoreURL: serverURL
},
description: 'NanoStore Publisher Example', // Shown to the Babbage user
orderID: invoice.ORDER_ID,
recipientPublicKey: invoice.identityKey,
amount: invoice.amount // This is the cost in satoshis
})
// After the payment, the file can be uploaded to NanoStore
const upload = await upload({
config: {
nanostoreURL: serverURL
},
uploadURL: pay.uploadURL,
publicURL: invoice.publicURL,
file,
serverURL,
onUploadProgress: prog => { // You can get progress updates
console.log(
'Progress:',
parseInt((prog.loaded / prog.total) * 100)
)
}
})
// You'll get the UHRP hash and the public URL after upload
console.log({
hash: upload.hash,
publicURL: upload.publicURL
})
As you can see in the above code, there are three phases to the publication of content with this library. First, an invoice is created where you specify the file size and the retention period of the content you are uploading. Then, you pay for the content, and finally, the content is uploaded to NanoStore.
Here's a more customized example. We've separated the "pay" phase into its derivePaymentInfo
and submitPayment
component parts, allowing for a custom transaction to be constructed. This is useful if, for example, there is a need for multiple outputs going to different places:
import [ invoice, derivePaymentInfo, submitPayment, upload ] from 'nanostore-publisher'
import { createAction } from '@babbage/sdk-ts'
// Create an invoice, like normal
const invoice = await invoice({
fileSize: file.size,
retentionPeriod: 86400
})
// Get the information needed for making the payment
const paymentInfo = await derivePaymentInfo({
recipientPublicKey: invoice.identityKey,
amount: invoice.amount // This is the cost in satoshis
})
// Create a custom transaction, potentially with other outputs
const payment = await createAction({
description: 'Custom payment',
outputs: [
{ script: '016a', satoshis: 1 }, // ...custom outputs
paymentInfo.output // payment output
]
})
// Submit the payment after the transaction is complete
const payment = await submitPayment({
orderID: invoice.ORDER_ID,
amount: invoice.amount,
payment,
derivationPrefix: paymentInfo.derivationPrefix,
derivationSuffix: paymentInfo.derivationSuffix,
vout: 1 // The payment output was at index 1 in the outputs array
})
// Upload the file as normal
const upload = await upload({
uploadURL: pay.uploadURL,
publicURL: invoice.publicURL,
file
})
Note, in the above example, that the two low-level payment functions replace the high-level pay
function.
If you simply want to publish a single file with default behavior, you can make use of the publishFile
function.
Example Usage in a React UI
// Publish the uploaded file
const uploadResult = await publishFile({
file,
retentionPeriod,
progressTracker: prog => {
setUploadProgress(
parseInt((prog.loaded / prog.total) * 100)
)
}
})
// Show the results in the UI
setResults({
hash: uploadResult.hash,
publicURL: uploadResult.publicURL
})
Creates an invoice for a NanoStore file hosting contract.
-
obj
Object All parameters are given in an object. (optional, default{}
)
Returns Promise<Object> The invoice object, containing message
giving details, identityKey
recipient's private key, amount
(satoshis), ORDER_ID
, for referencing this contract payment and passed to the upload
function. The object also contains publicURL
, which is the HTTP URL where the file will become available for the duration of the contract once uploaded and the status
.
Derives an output to pay for the NanoStore file hosting contract. After
payment, use submitPayment
to complete the payment process and get an
upload URL.
-
obj
Object All parameters are given in an object. (optional, default{}
)
Returns Promise<Object> The output object, contains the script
and the amount of satoshis
'.
Submit a manually-created payment for NanoStore hosting. Obtain an output
that must be included in the transaction by using derivePaymentInfo
, and
then provide the Everett envelope for the transaction here. Also use the
vout
parameter to specify which output in your transaction has paid the
invoice.
-
obj
Object All parameters are given in an object. (optional, default{}
)-
obj.config
Object config object, see config section. (optional, defaultCONFIG
) -
obj.orderID
String The hosting invoice reference. -
obj.amount
Number The number of satoshis being paid. -
obj.payment
Object The result of calling createAction which incorporates the payment output for the NanoStore hosting. Object that includesinputs
,mapiResponses
,rawTx
. -
obj.vout
Number The output from the Action which corresponds to the payment for NanoStore hosting -
obj.derivationPrefix
String The value returned fromderivePaymentInfo
-
obj.derivationSuffix
String The value returned fromderivePaymentInfo
-
Returns Promise<Object> The paymentResult object, contains the uploadURL
and the publicURL
and the status
'.
High-level function to automatically pay an invoice, using a Babbage SDK
createAction
call.
-
obj
Object All parameters are given in an object. (optional, default{}
)-
obj.config
Object config object, see config section. (optional, defaultCONFIG
) -
obj.description
String The description to be used for the payment. -
obj.orderID
String The hosting invoice reference. -
obj.recipientPublicKey
String Public key of the host receiving the payment. -
obj.amount
Number The number of satoshis being paid.
-
Returns Promise<Object> The pay object, contains the uploadURL
and the publicURL
and the status
'.
Uploads a file to NanoStore and pays an invoice, thereby starting the file hosting contract.
-
obj
Object? All parameters are given in an object. (optional, default{}
)-
obj.uploadURL
String? The external URL where the file is uploaded to host it. -
obj.publicURL
String? The public URL where the file can be downloaded from. -
obj.file
(File | object)? The file to upload. This is usually obtained by querying for your HTML form's file upload<input />
tag and referencingtagElement.files[0]
. Or using custom object as defined in publishFile.js -
obj.serverURL
String The URL of the NanoStore server to contract with. By default, the Babbage NanoStore server is used. (optional, defaulthttps://nanostore.babbage.systems
) -
obj.onUploadProgress
Function? A function called with periodic progress updates as the file uploads (optional, default()=>{}
) -
obj.config
(optional, defaultCONFIG
)
-
Returns Promise<Object> The publication object. Fields are published=true
, hash
(the UHRP URL of the new file), and publicURL
, the HTTP URL where the file is published.
High-level function to automatically pay an invoice, using a Babbage SDK
createAction
call, or a clientPrivateKey when in a server environment.
-
obj
Object All parameters are given in an object. (optional, default{}
)-
obj.config
Object config object, see config section. (optional, defaultCONFIG
) -
obj.file
(File | object) the File to upload given as File or custom object with the necessary data params (see below) -
obj.retentionPeriod
number how long the file should be retained -
obj.progressTracker
function function to provide updates on upload progress (optional, default()=>{}
)
-
Returns Promise<Object> The upload object, contains the hash
and the publicURL
and the status
'.
// Example compatible File object for publishing file data from a Buffer
const fileToUpload = {
dataAsBuffer,
size: dataAsBuffer.length,
type: 'image/png' // use 'mime' to determine file type
}
The license for the code in this repository is the Open BSV License.