Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created download functionality. #4

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
90 changes: 70 additions & 20 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ethers } from 'ethers'
import * as fs from 'fs'
import { createAsset } from './helpers/publish'
import fetch from 'cross-fetch'
import { download } from './helpers/download'

globalThis.fetch = fetch

Expand Down Expand Up @@ -65,9 +66,6 @@ export function activate(context: vscode.ExtensionContext) {
let publishAsset = vscode.commands.registerCommand(
'ocean-protocol.publishAsset',
async (config: any, filePath: string, privateKey: string) => {
vscode.window.showInformationMessage(`Private key: ${privateKey}`)
vscode.window.showInformationMessage(`File path: ${filePath}`)
vscode.window.showInformationMessage(`Config: ${JSON.stringify(config)}`)
if (!filePath) {
vscode.window.showErrorMessage('No file path provided.')
return
Expand All @@ -89,15 +87,8 @@ export function activate(context: vscode.ExtensionContext) {
// Set up the signer
const provider = new ethers.providers.JsonRpcProvider(process.env.RPC)

console.log('RPC URL:', config.rpcUrl)

console.log('NFT Factory Address:', config.nftFactoryAddress)
console.log('Ocean Token Address:', config.oceanTokenAddress)

const signer = new ethers.Wallet(privateKey, provider)
console.log('Signer:', signer)
const chainId = await signer.getChainId()
console.log('Chain ID:', chainId)
vscode.window.showInformationMessage(`Signer: ${signer}`)

// Test provider connectivity
Expand All @@ -111,22 +102,13 @@ export function activate(context: vscode.ExtensionContext) {
)
return
}
try {
const blockNumber = await provider.getBlockNumber()
console.log('Current block number:', blockNumber)
} catch (error) {
console.error('Error connecting to provider:', error)
}

const aquarius = new Aquarius(config.aquariusUrl)
console.log('Chain ID:', chainId)
vscode.window.showInformationMessage(`Chain ID: ${chainId}`)
const oceanConfig = new ConfigHelper().getConfig(chainId)
vscode.window.showInformationMessage(
`Ocean Config: ${JSON.stringify(oceanConfig)}`
)
console.log('Ocean Config:', oceanConfig)
console.log('creating asset:', asset)

const urlAssetId = await createAsset(
asset.nft.name,
Expand Down Expand Up @@ -156,7 +138,75 @@ export function activate(context: vscode.ExtensionContext) {
}
)

context.subscriptions.push(getAssetDetails, publishAsset)
let downloadAsset = vscode.commands.registerCommand(
'ocean-protocol.downloadAsset',
async (config: any, filePath: string, privateKey: string, assetDid: string) => {
if (!assetDid) {
vscode.window.showErrorMessage('No DID provided.')
return
}
if (!filePath) {
vscode.window.showErrorMessage('No file path provided.')
return
}

if (!privateKey) {
vscode.window.showErrorMessage('No private key provided.')
return
}

try {
// Set up the signer
const provider = new ethers.providers.JsonRpcProvider(process.env.RPC)
const signer = new ethers.Wallet(privateKey, provider)
const chainId = await signer.getChainId()
vscode.window.showInformationMessage(`Signer: ${signer}`)

// Test provider connectivity
try {
const network = provider.network
vscode.window.showInformationMessage(`Connected to network: ${network}`)
} catch (networkError) {
console.error('Error connecting to network:', networkError)
vscode.window.showErrorMessage(
`Error connecting to network: ${networkError.message}`
)
return
}

const aquarius = new Aquarius(config.aquariusUrl)
vscode.window.showInformationMessage(`Chain ID: ${chainId}`)
const oceanConfig = new ConfigHelper().getConfig(chainId)
vscode.window.showInformationMessage(
`Ocean Config: ${JSON.stringify(oceanConfig)}`
)

await download(
assetDid,
signer,
filePath,
aquarius,
undefined,
config.providerUrl
)

vscode.window.showInformationMessage(
`Asset download successfully. Path: ${filePath}`
)
} catch (error) {
console.error('Error details:', error)
if (error instanceof Error) {
vscode.window.showErrorMessage(`Error downloading asset: ${error.message}`)
} else {
vscode.window.showErrorMessage(
`An unknown error occurred while downloading the asset.`
)
}
}
}
)

context.subscriptions.push(getAssetDetails, publishAsset, downloadAsset)
}

export function deactivate() {}
99 changes: 99 additions & 0 deletions src/helpers/download.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import {
Aquarius,
Datatoken,
ProviderInstance,
ConfigHelper,
orderAsset
} from '@oceanprotocol/lib'
import { Signer } from 'ethers'
import { promises as fs } from 'fs'
import * as path from 'path'

export async function downloadFile(
url: string,
downloadPath: string,
index?: number
): Promise<any> {
const response = await fetch(url)
if (!response.ok) {
throw new Error('Response error.')
}

const defaultName = !isNaN(index) && index > -1 ? `file_${index}.out` : 'file.out'
let filename: string

try {
// try to get it from headers
filename = response.headers
.get('content-disposition')
.match(/attachment;filename=(.+)/)[1]
} catch {
filename = defaultName
}

const filePath = path.join(downloadPath, filename)
const data = await response.arrayBuffer()

try {
await fs.writeFile(filePath, Buffer.from(data))
} catch (err) {
throw new Error('Error while saving the file:', err.message)
}

return filename
}

export async function download(
did: string,
owner: Signer,
pathString: string = '.',
aquariusInstance: Aquarius,
macOsProviderUrl?: string,
providerUrl?: string
) {
const dataDdo = await aquariusInstance.waitForAqua(did)
if (!dataDdo) {
console.error('Error fetching DDO ' + did + '. Does this asset exists?')
return
}
let providerURI
if (!providerUrl) {
providerURI =
macOsProviderUrl && dataDdo.chainId === 8996
? macOsProviderUrl
: dataDdo.services[0].serviceEndpoint
} else {
providerURI = providerUrl
}
console.log('Downloading asset using provider: ', providerURI)
const { chainId } = await owner.provider.getNetwork()
console.log('Chain ID:', chainId)
const config = new ConfigHelper().getConfig(chainId)
console.log('Config:', config)
const datatoken = new Datatoken(owner, chainId)

const tx = await orderAsset(dataDdo, owner, config, datatoken, providerURI)

if (!tx) {
console.error('Error ordering access for ' + did + '. Do you have enough tokens?')
return
}

const orderTx = await tx.wait()

const urlDownloadUrl = await ProviderInstance.getDownloadUrl(
dataDdo.id,
dataDdo.services[0].id,
0,
orderTx.transactionHash,
providerURI,
owner
)
try {
const path = pathString ? pathString : '.'
const { filename } = await downloadFile(urlDownloadUrl, path)
console.log('File downloaded successfully:', path + '/' + filename)
} catch (e) {
console.log(`Download url dataset failed: ${e}`)
}
}
39 changes: 39 additions & 0 deletions src/viewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,45 @@ export class OceanProtocolViewProvider implements vscode.WebviewViewProvider {
}
});
</script>
<h3>Download Asset</h3>
<label for="privateKeyInput">Private Key</label>
<input id="privateKeyInput" type="password" placeholder="Enter your private key" />

<label for="assetDidInput">Asset DID</label>
<input id="assetDidInput" placeholder="Enter your asset DID" />

<label for="filePathInput">File Path</label>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by the way, file path is a bit of a confusing name as they don't have the file yet. It might be better to say download path to indicate this is where the file is going to be saved.

<input id="filePathInput" placeholder="Enter your file path" />

<button id="downloadAssetBtn">Download Asset</button>

<script>
const vscode = acquireVsCodeApi();
let selectedFilePath = '';

function getConfig() {
const defaultAquariusUrl = 'http://127.0.0.1:8001';
return {
rpcUrl: document.getElementById('rpcUrl').value || 'http://127.0.0.1:8545',
aquariusUrl: document.getElementById('nodeUrl').value || defaultAquariusUrl,
providerUrl: document.getElementById('nodeUrl').value || defaultAquariusUrl
};
}

document.getElementById('downloadAssetBtn').addEventListener('click', () => {
const config = getConfig();
const privateKey = document.getElementById('privateKeyInput').value;
const assetDidSelected = document.getElementById('assetDidInput').value;
const filePathSelected = document.getElementById('filePathInput').value;
vscode.postMessage({
type: 'downloadAsset',
privateKey: privateKey,
filePath: filePathSelected,
config: config,
assetDid: assetDidSelected
});
});
</script>
</body>
</html>
`
Expand Down