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

ACT support #543

Draft
wants to merge 17 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ the [releases tab](https://github.com/ethersphere/swarm-cli/releases).
- [Uploading a File](#uploading-a-file)
- [Creating an Identity](#creating-an-identity)
- [Uploading to a Feed](#uploading-to-a-feed)
- [Upload file with ACT](#upload-file-with-act)
- [Download file with ACT](#download-file-with-act)
- [Create grantees list](#create-grantees-list)
- [Get grantees list](#get-grantees-list)
- [Patch grantees list](#patch-grantees-list)
- [Description](#description)
- [Installation](#installation)
- [From npm](#from-npm)
Expand Down Expand Up @@ -68,6 +73,64 @@ the [releases tab](https://github.com/ethersphere/swarm-cli/releases).

![Swarm CLI Feed Upload Command](./docs/feed-upload.gif)

## Upload a file with ACT

```sh
swarm-cli upload <file> --act --stamp <postage_batch_id>
```

## Download a file with ACT

```sh
swarm-cli download <swarm_hash> <file> --act --act-history-address <swarm_history_address> --act-publisher <public_key>
```

## Create a grantees list

```sh
swarm-cli grantee create grantees.json --stamp <postage_batch_id>
```

`grantees.json`:

```json
{ "grantees": [
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12e8",
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12e9",
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12ee"
]
}
```

## Get a grantees list

```sh
swarm-cli grantee get <grantee_reference>
```

## Patch a grantees list

```sh
swarm-cli grantee patch grantees-patch.json \
--reference <grantee_reference> \
--history <grantee_history_reference> \
--stamp <postage_batch_id>
```

`grantees-patch.json`:

```json
{
"add": [
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12e7"
],
"revoke": [
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12e9",
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12ee"
]
}
```

# Description

> Manage your Bee node and interact with the Swarm network via the CLI
Expand Down
20 changes: 18 additions & 2 deletions src/command/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,22 @@ export class Download extends RootCommand implements LeafCommand {
public manifestDownload!: ManifestDownload

private address!: BzzAddress
private actReqHeaders: Record<string, string> = {}

public async run(): Promise<void> {
await super.init()
const { act, actTimestamp, actHistoryAddress, actPublisher } = this.manifestDownload

this.address = await makeBzzAddress(this.bee, this.manifestDownload.bzzUrl)
if (act) {
this.actReqHeaders = {
'Swarm-Act': 'true',
'Swarm-Act-Timestamp': actTimestamp,
'Swarm-Act-History-Address': actHistoryAddress,
'Swarm-Act-Publisher': actPublisher,
}
}

this.address = await makeBzzAddress(this.bee, this.manifestDownload.bzzUrl, this.actReqHeaders)

if (await this.isManifest()) {
this.manifestDownload.address = this.address
Expand All @@ -29,7 +40,12 @@ export class Download extends RootCommand implements LeafCommand {
}

private async downloadFile(): Promise<void> {
const response = await this.bee.downloadFile(this.address.hash)
const response = await (this.manifestDownload.act
? this.bee.downloadFile(this.address.hash, '', {
headers: this.actReqHeaders,
})
: this.bee.downloadFile(this.address.hash))

const { name, data } = response

if (this.manifestDownload.stdout) {
Expand Down
2 changes: 1 addition & 1 deletion src/command/feed/feed-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export class FeedCommand extends RootCommand {
)
const { reference } = await writer.upload(stamp, chunkReference as Reference)

return { reference, manifest }
return { reference: reference.toString(), manifest }
} finally {
spinner.stop()
}
Expand Down
40 changes: 40 additions & 0 deletions src/command/grantee/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Argument, LeafCommand, Option } from 'furious-commander'
import { GranteeCommand } from './grantee-command'
import { stampProperties } from '../../utils/option'
import { createKeyValue } from '../../utils/text'
import fs from 'fs'

export class Create extends GranteeCommand implements LeafCommand {
public readonly name = 'create'
public readonly description = 'Create grantee list'
private actReqHeaders: Record<string, string> = {}

@Argument({
key: 'path',
description: 'Path to the file with grantee list',
required: true,
autocompletePath: true,
conflicts: 'stdin',
})
public path!: string

@Option({ key: 'stdin', type: 'boolean', description: 'Take data from standard input', conflicts: 'path' })
public stdin!: boolean

@Option(stampProperties)
public stamp!: string

public async run(): Promise<void> {
await super.init()
this.actReqHeaders = {
'Swarm-Act': 'true',
}
const granteesFile = fs.readFileSync(this.path, 'utf8')
const createGrantees = JSON.parse(granteesFile)
const grantees = createGrantees.grantees

const response = await this.bee.createGrantees(this.stamp, grantees)
this.console.log(createKeyValue('Grantee reference', response.ref))
this.console.log(createKeyValue('Grantee history reference', response.historyref))
}
}
22 changes: 22 additions & 0 deletions src/command/grantee/get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Argument, LeafCommand } from 'furious-commander'
import { GranteeCommand } from './grantee-command'
import { createKeyValue } from '../../utils/text'

export class Get extends GranteeCommand implements LeafCommand {
public readonly name = 'get'
public readonly description = 'Get grantee list'

@Argument({
key: 'reference',
description: 'Grantee list reference',
required: true,
conflicts: 'stdin',
})
public reference!: string

public async run(): Promise<void> {
await super.init()
const response = await this.bee.getGrantees(this.reference)
this.console.log(createKeyValue('Grantee public keys', response.data.join('\n')))
}
}
3 changes: 3 additions & 0 deletions src/command/grantee/grantee-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { RootCommand } from '../root-command'

export class GranteeCommand extends RootCommand {}
12 changes: 12 additions & 0 deletions src/command/grantee/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { GroupCommand } from 'furious-commander'
import { Create } from './create'
import { Get } from './get'
import { Patch } from './patch'

export class Grantee implements GroupCommand {
public readonly name = 'grantee'

public readonly description = 'Create, Get, Patch grantee list'

public subCommandClasses = [Create, Get, Patch]
}
58 changes: 58 additions & 0 deletions src/command/grantee/patch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Argument, LeafCommand, Option } from 'furious-commander'
import { GranteeCommand } from './grantee-command'
import { stampProperties } from '../../utils/option'
import { createKeyValue } from '../../utils/text'
import fs from 'fs'

export class Patch extends GranteeCommand implements LeafCommand {
public readonly name = 'patch'
public readonly description = 'Patch grantee list'
private actReqHeaders: Record<string, string> = {}

@Argument({
key: 'path',
description: 'Path to the JSON file with grantee patch (add, revoke)',
required: true,
autocompletePath: true,
conflicts: 'stdin',
})
public path!: string

@Option({ key: 'stdin', type: 'boolean', description: 'Take data from standard input', conflicts: 'path' })
public stdin!: boolean

@Option(stampProperties)
public stamp!: string

@Option({
key: 'reference',
type: 'string',
description: 'Encrypted grantee list reference with 128 characters length',
length: 128,
required: true,
})
public eref!: string

@Option({
key: 'history',
type: 'string',
description: 'Swarm address reference to the ACT history entry',
length: 64,
required: true,
})
public history!: string

public async run(): Promise<void> {
await super.init()
this.actReqHeaders = {
'Swarm-Act': 'true',
'Swarm-Act-Timestamp': Date.now().toString(),
}
const patchContent = fs.readFileSync(this.path, 'utf8')
const patch = JSON.parse(patchContent)

const response = await this.bee.patchGrantees(this.stamp, this.eref, this.history, patch, this.actReqHeaders)
this.console.log(createKeyValue('Grantee reference', response.ref))
this.console.log(createKeyValue('Grantee history reference', response.historyref))
}
}
14 changes: 14 additions & 0 deletions src/command/manifest/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ export class Download extends ManifestCommand implements LeafCommand {
@Option({ key: 'stdout', type: 'boolean', description: 'Print to stdout (single files only)' })
public stdout!: boolean

@Option({ key: 'act', type: 'boolean', description: 'Download with ACT', default: false })
public act!: boolean

@Option({ key: 'act-timestamp', type: 'string', description: 'ACT history timestamp', default: '1' })
public actTimestamp!: string

// required if act is true
@Option({ key: 'act-history-address', type: 'string', description: 'ACT history address', required: { when: 'act' } })
public actHistoryAddress!: string

// required if act is true
@Option({ key: 'act-publisher', type: 'string', description: 'ACT publisher', required: { when: 'act' } })
public actPublisher!: string

public async run(): Promise<void> {
await super.init()

Expand Down
Loading
Loading