Skip to content

Commit fd879bc

Browse files
ferencsaraiFerenc Sárai
andauthored
feat: add act commands (#569)
* feat: apply act.patch * fix: download test * fix: lint warning * feat: migrate form @upcoming/bee-js to @ethersphere/bee-js v9.0.2, upload with same act-history test * feat: add act upload test with another file and with same history address --------- Co-authored-by: Ferenc Sárai <[email protected]>
1 parent bb4c4ae commit fd879bc

20 files changed

+470
-25
lines changed

README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ the [releases tab](https://github.com/ethersphere/swarm-cli/releases).
1919
- [Uploading a File](#uploading-a-file)
2020
- [Creating an Identity](#creating-an-identity)
2121
- [Uploading to a Feed](#uploading-to-a-feed)
22+
- [Upload file with ACT](#upload-file-with-act)
23+
- [Download file with ACT](#download-file-with-act)
24+
- [Create grantees list](#create-grantees-list)
25+
- [Get grantees list](#get-grantees-list)
26+
- [Patch grantees list](#patch-grantees-list)
2227
- [Description](#description)
2328
- [Installation](#installation)
2429
- [From npm](#from-npm)
@@ -68,6 +73,64 @@ the [releases tab](https://github.com/ethersphere/swarm-cli/releases).
6873

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

76+
## Upload a file with ACT
77+
78+
```sh
79+
swarm-cli upload <file> --act --stamp <postage_batch_id>
80+
```
81+
82+
## Download a file with ACT
83+
84+
```sh
85+
swarm-cli download <swarm_hash> <file> --act --act-history-address <swarm_history_address> --act-publisher <public_key>
86+
```
87+
88+
## Create a grantees list
89+
90+
```sh
91+
swarm-cli grantee create grantees.json --stamp <postage_batch_id>
92+
```
93+
94+
`grantees.json`:
95+
96+
```json
97+
{ "grantees": [
98+
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12e8",
99+
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12e9",
100+
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12ee"
101+
]
102+
}
103+
```
104+
105+
## Get a grantees list
106+
107+
```sh
108+
swarm-cli grantee get <grantee_reference>
109+
```
110+
111+
## Patch a grantees list
112+
113+
```sh
114+
swarm-cli grantee patch grantees-patch.json \
115+
--reference <grantee_reference> \
116+
--history <grantee_history_reference> \
117+
--stamp <postage_batch_id>
118+
```
119+
120+
`grantees-patch.json`:
121+
122+
```json
123+
{
124+
"add": [
125+
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12e7"
126+
],
127+
"revoke": [
128+
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12e9",
129+
"02ceff1422a7026ba54ad89967d81f2805a55eb3d05f64eb5c49ea6024212b12ee"
130+
]
131+
}
132+
```
133+
71134
# Description
72135

73136
> Manage your Bee node and interact with the Swarm network via the CLI
@@ -124,6 +187,7 @@ stamp Buy, list and show postage stamps
124187
pss Send, receive, or subscribe to PSS messages
125188
manifest Operate on manifests
126189
utility Utility commands for managing wallets
190+
grantee Create, Get, Patch grantee list
127191
128192
Run 'swarm-cli GROUP --help' to see available commands in a group
129193

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@
6262
"typescript": "^4.8.4"
6363
},
6464
"dependencies": {
65-
"@ethersphere/bee-js": "^9.0.1",
66-
"cafe-utility": "^27.14.2",
65+
"@ethersphere/bee-js": "^9.0.2",
66+
"cafe-utility": "^27.14.0",
6767
"chalk": "^2.4.2",
6868
"cli-progress": "^3.11.2",
6969
"ethereumjs-wallet": "^1.0.2",

src/command/download.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,20 @@ export class Download extends RootCommand implements LeafCommand {
1414
public manifestDownload!: ManifestDownload
1515

1616
private address!: BzzAddress
17+
private actReqHeaders: Record<string, string> = {}
1718

1819
public async run(): Promise<void> {
1920
super.init()
2021

22+
if (this.manifestDownload.act) {
23+
this.actReqHeaders = {
24+
'Swarm-Act': 'true',
25+
'Swarm-Act-Timestamp': this.manifestDownload.actTimestamp,
26+
'Swarm-Act-History-Address': this.manifestDownload.actHistoryAddress,
27+
'Swarm-Act-Publisher': this.manifestDownload.actPublisher,
28+
}
29+
}
30+
2131
this.address = await makeBzzAddress(this.bee, this.manifestDownload.bzzUrl)
2232

2333
if (await this.isManifest()) {
@@ -29,7 +39,15 @@ export class Download extends RootCommand implements LeafCommand {
2939
}
3040

3141
private async downloadData(): Promise<void> {
32-
const response = await this.bee.downloadData(this.address.hash)
42+
const downloadOptions = this.manifestDownload.act
43+
? {
44+
actPublisher: this.manifestDownload.actPublisher,
45+
actHistoryAddress: this.manifestDownload.actHistoryAddress,
46+
actTimestamp: this.manifestDownload.actTimestamp,
47+
}
48+
: undefined
49+
50+
const response = await this.bee.downloadData(this.address.hash, downloadOptions)
3351

3452
if (this.manifestDownload.stdout) {
3553
process.stdout.write(response.toUtf8())

src/command/grantee/create.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Argument, LeafCommand, Option } from 'furious-commander'
2+
import { GranteeCommand } from './grantee-command'
3+
import { stampProperties } from '../../utils/option'
4+
import { createKeyValue } from '../../utils/text'
5+
import fs from 'fs'
6+
7+
export class Create extends GranteeCommand implements LeafCommand {
8+
public readonly name = 'create'
9+
public readonly description = 'Create grantee list'
10+
private actReqHeaders: Record<string, string> = {}
11+
12+
@Argument({
13+
key: 'path',
14+
description: 'Path to the file with grantee list',
15+
required: true,
16+
autocompletePath: true,
17+
conflicts: 'stdin',
18+
})
19+
public path!: string
20+
21+
@Option({ key: 'stdin', type: 'boolean', description: 'Take data from standard input', conflicts: 'path' })
22+
public stdin!: boolean
23+
24+
@Option(stampProperties)
25+
public stamp!: string
26+
27+
public async run(): Promise<void> {
28+
await super.init()
29+
this.actReqHeaders = {
30+
'Swarm-Act': 'true',
31+
}
32+
const granteesFile = fs.readFileSync(this.path, 'utf8')
33+
const createGrantees = JSON.parse(granteesFile)
34+
const grantees = createGrantees.grantees
35+
36+
const response = await this.bee.createGrantees(this.stamp, grantees)
37+
this.console.log(createKeyValue('Grantee reference', response.ref.toHex()))
38+
this.console.log(createKeyValue('Grantee history reference', response.historyref.toHex()))
39+
}
40+
}

src/command/grantee/get.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Argument, LeafCommand } from 'furious-commander'
2+
import { GranteeCommand } from './grantee-command'
3+
import { createKeyValue } from '../../utils/text'
4+
5+
export class Get extends GranteeCommand implements LeafCommand {
6+
public readonly name = 'get'
7+
public readonly description = 'Get grantee list'
8+
9+
@Argument({
10+
key: 'reference',
11+
description: 'Grantee list reference',
12+
required: true,
13+
conflicts: 'stdin',
14+
})
15+
public reference!: string
16+
17+
public async run(): Promise<void> {
18+
await super.init()
19+
const response = await this.bee.getGrantees(this.reference)
20+
this.console.log(
21+
createKeyValue('Grantee public keys', response.grantees.map(grantee => grantee.toCompressedHex()).join('\n')),
22+
)
23+
}
24+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { RootCommand } from '../root-command'
2+
3+
export class GranteeCommand extends RootCommand {}

src/command/grantee/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { GroupCommand } from 'furious-commander'
2+
import { Create } from './create'
3+
import { Get } from './get'
4+
import { Patch } from './patch'
5+
6+
export class Grantee implements GroupCommand {
7+
public readonly name = 'grantee'
8+
9+
public readonly description = 'Create, Get, Patch grantee list'
10+
11+
public subCommandClasses = [Create, Get, Patch]
12+
}

src/command/grantee/patch.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { Argument, LeafCommand, Option } from 'furious-commander'
2+
import { GranteeCommand } from './grantee-command'
3+
import { stampProperties } from '../../utils/option'
4+
import { createKeyValue } from '../../utils/text'
5+
import fs from 'fs'
6+
7+
export class Patch extends GranteeCommand implements LeafCommand {
8+
public readonly name = 'patch'
9+
public readonly description = 'Patch grantee list'
10+
private actReqHeaders: Record<string, string> = {}
11+
12+
@Argument({
13+
key: 'path',
14+
description: 'Path to the JSON file with grantee patch (add, revoke)',
15+
required: true,
16+
autocompletePath: true,
17+
conflicts: 'stdin',
18+
})
19+
public path!: string
20+
21+
@Option({ key: 'stdin', type: 'boolean', description: 'Take data from standard input', conflicts: 'path' })
22+
public stdin!: boolean
23+
24+
@Option(stampProperties)
25+
public stamp!: string
26+
27+
@Option({
28+
key: 'reference',
29+
type: 'string',
30+
description: 'Encrypted grantee list reference with 128 characters length',
31+
length: 128,
32+
required: true,
33+
})
34+
public eref!: string
35+
36+
@Option({
37+
key: 'history',
38+
type: 'string',
39+
description: 'Swarm address reference to the ACT history entry',
40+
length: 64,
41+
required: true,
42+
})
43+
public history!: string
44+
45+
public async run(): Promise<void> {
46+
await super.init()
47+
this.actReqHeaders = {
48+
'Swarm-Act': 'true',
49+
'Swarm-Act-Timestamp': Date.now().toString(),
50+
}
51+
const patchContent = fs.readFileSync(this.path, 'utf8')
52+
const patch = JSON.parse(patchContent)
53+
54+
const response = await this.bee.patchGrantees(this.stamp, this.eref, this.history, patch, this.actReqHeaders)
55+
this.console.log(createKeyValue('Grantee reference', response.ref.toHex()))
56+
this.console.log(createKeyValue('Grantee history reference', response.historyref.toHex()))
57+
}
58+
}

src/command/manifest/download.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@ export class Download extends RootCommand implements LeafCommand {
2323
@Option({ key: 'stdout', type: 'boolean', description: 'Print to stdout (single files only)' })
2424
public stdout!: boolean
2525

26+
@Option({ key: 'act', type: 'boolean', description: 'Download with ACT', default: false })
27+
public act!: boolean
28+
29+
@Option({ key: 'act-timestamp', type: 'string', description: 'ACT history timestamp', default: '1' })
30+
public actTimestamp!: string
31+
32+
// required if act is true
33+
@Option({ key: 'act-history-address', type: 'string', description: 'ACT history address', required: { when: 'act' } })
34+
public actHistoryAddress!: string
35+
36+
// required if act is true
37+
@Option({ key: 'act-publisher', type: 'string', description: 'ACT publisher', required: { when: 'act' } })
38+
public actPublisher!: string
39+
2640
public async run(): Promise<void> {
2741
super.init()
2842

0 commit comments

Comments
 (0)