diff --git a/.changeset/ten-apes-matter.md b/.changeset/ten-apes-matter.md new file mode 100644 index 0000000..ec8a920 --- /dev/null +++ b/.changeset/ten-apes-matter.md @@ -0,0 +1,5 @@ +--- +"@protocol.land/pages": minor +--- + +feat: Add tx subsidization diff --git a/lib/arweaveHelper.js b/lib/arweaveHelper.js index 3439a68..c14a996 100644 --- a/lib/arweaveHelper.js +++ b/lib/arweaveHelper.js @@ -1,5 +1,5 @@ const Arweave = require('arweave'); -const {ArweaveSigner, createData} = require('arbundles'); +const {ArweaveSigner, bundleAndSignData, createData} = require('arbundles'); const common = require('./common.js'); async function getAddress(wallet) { @@ -18,11 +18,16 @@ function initArweave() { async function uploadFile(file, tags) { try { - const bundlrTxId = await bundlrUpload(file, tags); - return bundlrTxId; - } catch (error) { - const arweaveTxId = await arweaveUpload(file, tags); - return arweaveTxId; + const uploadedTx = await subsidizedUpload(file, tags); + return uploadedTx.data.repoTxId; + } catch (e) { + try { + const turboTxId = await turboUpload(file, tags); + return turboTxId; + } catch (error) { + const arweaveTxId = await arweaveUpload(file, tags); + return arweaveTxId; + } } } @@ -40,14 +45,18 @@ async function arweaveUpload(file, tags) { } await arweave.transactions.sign(tx, jwk); - const response = await arweave.transactions.post(tx); - if (response.status !== 200) { + const uploader = await arweave.transactions.getUploader(tx); + while (!uploader.isComplete) { + await uploader.uploadChunk(); + } + + if (uploader.lastResponseStatus !== 200) { // throw error if arweave tx wasn't posted - throw `[ arweave ] Posting file to arweave failed.\n\tError: '${ - response.status + throw `[ arweave ] Uploading file to arweave failed.\n\tError: '${ + uploader.lastResponseStatus }' - '${ - response.statusText + uploader.lastResponseError }'\n\tCheck if you have plenty $AR to upload ~${Math.ceil( dataSize / 1024 )} KB of data.`; @@ -56,13 +65,13 @@ async function arweaveUpload(file, tags) { return tx.id; } -async function bundlrUpload(file, tags) { +async function turboUpload(file, tags) { const jwk = common.getWallet(); if (!jwk) { - throw '[ bundlr ] No jwk wallet supplied'; + throw '[ turbo ] No jwk wallet supplied'; } - const node = 'https://node2.bundlr.network'; + const node = 'https://turbo.ardrive.io'; const uint8ArrayFile = new Uint8Array(file); const signer = new ArweaveSigner(jwk); @@ -80,12 +89,51 @@ async function bundlrUpload(file, tags) { if (res.status >= 400) { throw new Error( - `[ bundlr ] Posting file with bundlr failed. Error: ${res.status} - ${res.statusText}` + `[ turbo ] Uploading file with turbo failed. Error: ${res.status} - ${res.statusText}` ); } return dataItem.id; } +async function subsidizedUpload(zipBuffer, tags) { + const jwk = common.getWallet(); + if (!jwk) { + throw 'No jwk wallet supplied'; + } + + const node = 'https://subsidize.saikranthi.dev/api/v1/postrepo'; + const uint8ArrayZip = new Uint8Array(zipBuffer); + const signer = new ArweaveSigner(jwk); + const address = await getAddress(); + + const dataItem = createData(uint8ArrayZip, signer, {tags}); + await dataItem.sign(signer); + + const bundle = await bundleAndSignData([dataItem], signer); + + const res = await fetch(`${node}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + body: JSON.stringify({ + txBundle: bundle.getRaw(), + platform: 'CLI', + owner: address, + }), + }); + const upload = await res.json(); + + if (!upload || !upload.success) { + throw new Error( + `[ PL SUBSIDIZE ] Uploading failed. Error: ${res.status} - ${res.statusText}` + ); + } + + return upload; +} + exports.getAddress = getAddress; exports.uploadFile = uploadFile;